* Create a mapping between FR_TYPE_* and valid FR_DER_TAG_*'s
*/
static const bool *fr_type_to_der_tags[FR_DER_TAG_MAX] = {
+ [FR_TYPE_IPV4_ADDR] = (bool [FR_DER_TAG_MAX]) {
+ [FR_DER_TAG_BITSTRING] = true,
+ },
+
+ [FR_TYPE_IPV6_ADDR] = (bool [FR_DER_TAG_MAX]) {
+ [FR_DER_TAG_BITSTRING] = true,
+ },
+
[FR_TYPE_BOOL] = (bool [FR_DER_TAG_MAX]) {
[FR_DER_TAG_BOOLEAN] = true,
[FR_DER_TAG_INTEGER] = true,
fr_strerror_const("Cannot use 'tlv' in DER. Please use 'sequence'");
return false;
- case FR_TYPE_IPV4_ADDR:
case FR_TYPE_IPV4_PREFIX:
- case FR_TYPE_IPV6_ADDR:
case FR_TYPE_IPV6_PREFIX:
case FR_TYPE_IFID:
case FR_TYPE_COMBO_IP_ADDR:
}
static const fr_der_tag_t fr_type_to_der_tag_defaults[FR_TYPE_MAX + 1] = {
+ [FR_TYPE_OCTETS] = FR_DER_TAG_OCTETSTRING,
+ [FR_TYPE_STRING] = FR_DER_TAG_UTF8_STRING,
+
+ [FR_TYPE_IPV4_ADDR] = FR_DER_TAG_BITSTRING,
+ [FR_TYPE_IPV6_ADDR] = FR_DER_TAG_BITSTRING,
+
[FR_TYPE_BOOL] = FR_DER_TAG_BOOLEAN,
+
[FR_TYPE_UINT8] = FR_DER_TAG_INTEGER,
[FR_TYPE_UINT16] = FR_DER_TAG_INTEGER,
[FR_TYPE_UINT32] = FR_DER_TAG_INTEGER,
[FR_TYPE_INT16] = FR_DER_TAG_INTEGER,
[FR_TYPE_INT32] = FR_DER_TAG_INTEGER,
[FR_TYPE_INT64] = FR_DER_TAG_INTEGER,
- [FR_TYPE_OCTETS] = FR_DER_TAG_OCTETSTRING,
- [FR_TYPE_STRING] = FR_DER_TAG_UTF8_STRING,
[FR_TYPE_DATE] = FR_DER_TAG_GENERALIZED_TIME,
[FR_TYPE_TLV] = FR_DER_TAG_SEQUENCE,
[FR_TYPE_STRUCT] = FR_DER_TAG_SEQUENCE,
static ssize_t fr_der_decode_pair_dbuff(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-static ssize_t fr_der_decode_boolean(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *in,
- fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_integer(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *in,
- fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_bitstring(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_octetstring(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_null(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *in,
- fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_utf8_string(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_sequence(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_set(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *in,
- fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_printable_string(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_t61_string(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_ia5_string(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_utc_time(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_generalized_time(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_visible_string(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_general_string(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-static ssize_t fr_der_decode_universal_string(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
- fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
-
-/*
- * We have per-type function names to make it clear that different types have different decoders.
- * However, the methods to decode them are the same. So rather than having trampoline functions, we just
- * use defines.
- */
-#define fr_der_decode_enumerated fr_der_decode_integer
-
-static fr_der_tag_decode_t tag_funcs[FR_DER_TAG_MAX] = {
- [FR_DER_TAG_BOOLEAN] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_boolean },
- [FR_DER_TAG_INTEGER] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_integer },
- [FR_DER_TAG_BITSTRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_bitstring },
- [FR_DER_TAG_OCTETSTRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_octetstring },
- [FR_DER_TAG_NULL] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_null },
- [FR_DER_TAG_ENUMERATED] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_enumerated },
- [FR_DER_TAG_UTF8_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_utf8_string },
- [FR_DER_TAG_SEQUENCE] = { .constructed = FR_DER_TAG_CONSTRUCTED, .decode = fr_der_decode_sequence },
- [FR_DER_TAG_SET] = { .constructed = FR_DER_TAG_CONSTRUCTED, .decode = fr_der_decode_set },
- [FR_DER_TAG_PRINTABLE_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE,
- .decode = fr_der_decode_printable_string },
- [FR_DER_TAG_T61_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_t61_string },
- [FR_DER_TAG_IA5_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_ia5_string },
- [FR_DER_TAG_UTC_TIME] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_utc_time },
- [FR_DER_TAG_GENERALIZED_TIME] = { .constructed = FR_DER_TAG_PRIMITIVE,
- .decode = fr_der_decode_generalized_time },
- [FR_DER_TAG_VISIBLE_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_visible_string },
- [FR_DER_TAG_GENERAL_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_general_string },
- [FR_DER_TAG_UNIVERSAL_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE,
- .decode = fr_der_decode_universal_string },
-};
-
static ssize_t fr_der_decode_string(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *in,
bool const allowed_chars[], fr_der_decode_ctx_t *decode_ctx) CC_HINT(nonnull(1,2,3,4,6));
return fr_der_decode_string(ctx, out, parent, in, allowed_chars, decode_ctx);
}
+/*
+ * We have per-type function names to make it clear that different types have different decoders.
+ * However, the methods to decode them are the same. So rather than having trampoline functions, we just
+ * use defines.
+ */
+#define fr_der_decode_enumerated fr_der_decode_integer
+
static ssize_t fr_der_decode_general_string(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
fr_dbuff_t *in, UNUSED fr_der_decode_ctx_t *decode_ctx)
{
return fr_der_decode_string(ctx, out, parent, in, NULL, decode_ctx);
}
+static ssize_t fr_der_decode_ipv4_addr(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
+ fr_dbuff_t *in, UNUSED fr_der_decode_ctx_t *decode_ctx)
+{
+ uint8_t byte;
+ fr_pair_t *vp;
+ fr_dbuff_t our_in = FR_DBUFF(in);
+
+ if (fr_dbuff_remaining(&our_in) != 1 + sizeof(vp->vp_ipv4addr)) {
+ fr_strerror_printf("Invalid ipv4addr size. Expected %zu, got %zu",
+ 1 + sizeof(vp->vp_ipv4addr), fr_dbuff_remaining(&our_in));
+ return -1;
+ }
+
+ FR_DBUFF_OUT_RETURN(&byte, &our_in);
+ if (byte != 0) {
+ fr_strerror_printf("Invalid ipv4addr prefix is non-zero (%02x)", byte);
+ return -1;
+ }
+
+ vp = fr_pair_afrom_da(ctx, parent);
+ if (unlikely(!vp)) {
+ fr_strerror_const("Out of memory");
+ return -1;
+ }
+
+ vp->vp_ip.af = AF_INET;
+ vp->vp_ip.prefix = 32;
+ FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *) &vp->vp_ipv4addr, &our_in, sizeof(vp->vp_ipv4addr));
+
+ fr_pair_append(out, vp);
+
+ return fr_dbuff_set(in, &our_in);
+}
+
+static ssize_t fr_der_decode_ipv6_addr(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
+ fr_dbuff_t *in, UNUSED fr_der_decode_ctx_t *decode_ctx)
+{
+ uint8_t byte;
+ fr_pair_t *vp;
+ fr_dbuff_t our_in = FR_DBUFF(in);
+
+ if (fr_dbuff_remaining(&our_in) != 1 + sizeof(vp->vp_ipv6addr)) {
+ fr_strerror_printf("Invalid ipv6addr size. Expected %zu, got %zu",
+ 1 + sizeof(vp->vp_ipv6addr), fr_dbuff_remaining(&our_in));
+ return -1;
+ }
+
+ FR_DBUFF_OUT_RETURN(&byte, &our_in);
+ if (byte != 0) {
+ fr_strerror_printf("Invalid ipv6addr prefix is non-zero (%02x)", byte);
+ return -1;
+ }
+
+ vp = fr_pair_afrom_da(ctx, parent);
+ if (unlikely(!vp)) {
+ fr_strerror_const("Out of memory");
+ return -1;
+ }
+
+ vp->vp_ip.af = AF_INET;
+ vp->vp_ip.prefix = 128;
+ FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *) &vp->vp_ipv6addr, &our_in, sizeof(vp->vp_ipv6addr));
+
+ fr_pair_append(out, vp);
+
+ return fr_dbuff_set(in, &our_in);
+}
+
+static const fr_der_tag_decode_t tag_funcs[FR_DER_TAG_MAX] = {
+ [FR_DER_TAG_BOOLEAN] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_boolean },
+ [FR_DER_TAG_INTEGER] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_integer },
+ [FR_DER_TAG_BITSTRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_bitstring },
+ [FR_DER_TAG_OCTETSTRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_octetstring },
+ [FR_DER_TAG_NULL] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_null },
+ [FR_DER_TAG_ENUMERATED] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_enumerated },
+ [FR_DER_TAG_UTF8_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_utf8_string },
+ [FR_DER_TAG_SEQUENCE] = { .constructed = FR_DER_TAG_CONSTRUCTED, .decode = fr_der_decode_sequence },
+ [FR_DER_TAG_SET] = { .constructed = FR_DER_TAG_CONSTRUCTED, .decode = fr_der_decode_set },
+ [FR_DER_TAG_PRINTABLE_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE,
+ .decode = fr_der_decode_printable_string },
+ [FR_DER_TAG_T61_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_t61_string },
+ [FR_DER_TAG_IA5_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_ia5_string },
+ [FR_DER_TAG_UTC_TIME] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_utc_time },
+ [FR_DER_TAG_GENERALIZED_TIME] = { .constructed = FR_DER_TAG_PRIMITIVE,
+ .decode = fr_der_decode_generalized_time },
+ [FR_DER_TAG_VISIBLE_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_visible_string },
+ [FR_DER_TAG_GENERAL_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_general_string },
+ [FR_DER_TAG_UNIVERSAL_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE,
+ .decode = fr_der_decode_universal_string },
+};
+
+static const fr_der_tag_decode_t type_funcs[FR_TYPE_MAX] = {
+ [FR_TYPE_IPV4_ADDR] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_ipv4_addr },
+ [FR_TYPE_IPV6_ADDR] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_ipv6_addr },
+};
+
/** Decode the tag and length fields of a DER encoded structure
*
* @param[in] parent Parent attribute
fr_dbuff_t our_in = FR_DBUFF(in);
uint8_t tag_byte;
uint8_t len_byte;
- fr_der_tag_decode_t *func;
+ fr_der_tag_decode_t const *func;
fr_der_tag_class_t tag_class;
fr_der_tag_constructed_t constructed;
fr_der_attr_flags_t const *flags;
return -1;
}
- func = &tag_funcs[*tag];
+ if (parent) switch (parent->type) {
+ case FR_TYPE_IPV4_ADDR:
+ case FR_TYPE_IPV6_ADDR:
+ func = &type_funcs[parent->type];
+ break;
+
+ default:
+ func = &tag_funcs[*tag];
+ break;
+ } else {
+ func = &tag_funcs[*tag];
+ }
/*
* Check if the tag is an OID. OID tags will be handled differently
fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx)
{
fr_dbuff_t our_in = FR_DBUFF(in);
- fr_der_tag_decode_t *func;
+ fr_der_tag_decode_t const *func;
ssize_t slen;
uint8_t tag;
size_t len;
return fr_dbuff_set(in, &our_in);
}
- func = &tag_funcs[tag];
+ switch (parent->type) {
+ case FR_TYPE_IPV4_ADDR:
+ case FR_TYPE_IPV6_ADDR:
+ func = &type_funcs[parent->type];
+ break;
+
+ default:
+ func = &tag_funcs[tag];
+ break;
+ }
+ fr_assert(func != NULL);
/*
* Enforce limits on min/max.
fr_der_encode_t encode;
} fr_der_tag_encode_t;
-static ssize_t fr_der_encode_boolean(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull(1,2));
-static ssize_t fr_der_encode_integer(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull(1,2));
-static ssize_t fr_der_encode_bitstring(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull);
-static ssize_t fr_der_encode_octetstring(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull);
-static ssize_t fr_der_encode_null(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull(2));
-static ssize_t fr_der_encode_oid(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull(1,2));
-static ssize_t fr_der_encode_sequence(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull);
-static ssize_t fr_der_encode_set(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull);
-static ssize_t fr_der_encode_utc_time(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull(1,2));
-static ssize_t fr_der_encode_generalized_time(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull(1,2));
static ssize_t fr_der_encode_oid_value_pair(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull);
-static ssize_t fr_der_encode_string(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx) CC_HINT(nonnull(1,2));
-
/*
* We have per-type function names to make it clear that different types have different encoders.
* However, the methods to encode them are the same. So rather than having trampoline functions, we just
void *encode_ctx);
static ssize_t der_encode_pair(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *encode_ctx) CC_HINT(nonnull);
-static fr_der_tag_encode_t tag_funcs[FR_DER_TAG_MAX] = {
- [FR_DER_TAG_BOOLEAN] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_boolean },
- [FR_DER_TAG_INTEGER] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_integer },
- [FR_DER_TAG_BITSTRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_bitstring },
- [FR_DER_TAG_OCTETSTRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_octetstring },
- [FR_DER_TAG_NULL] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_null },
- [FR_DER_TAG_OID] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_oid },
- [FR_DER_TAG_ENUMERATED] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_enumerated },
- [FR_DER_TAG_UTF8_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
- [FR_DER_TAG_SEQUENCE] = { .constructed = FR_DER_TAG_CONSTRUCTED, .encode = fr_der_encode_sequence },
- [FR_DER_TAG_SET] = { .constructed = FR_DER_TAG_CONSTRUCTED, .encode = fr_der_encode_set },
- [FR_DER_TAG_PRINTABLE_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE,
- .encode = fr_der_encode_string },
- [FR_DER_TAG_T61_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
- [FR_DER_TAG_IA5_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
- [FR_DER_TAG_UTC_TIME] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_utc_time },
- [FR_DER_TAG_GENERALIZED_TIME] = { .constructed = FR_DER_TAG_PRIMITIVE,
- .encode = fr_der_encode_generalized_time },
- [FR_DER_TAG_VISIBLE_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
- [FR_DER_TAG_GENERAL_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
- [FR_DER_TAG_UNIVERSAL_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE,
- .encode = fr_der_encode_string },
-};
-
/** Compare two pairs by their tag number.
*
* @param[in] a First pair.
* because this information should be retained when encoding/decoding.
*/
if (vp->vp_length == 0) {
- FR_DBUFF_IN_RETURN(&our_dbuff, 0x00);
+ FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) 0x00);
} else {
FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, vp->vp_octets, vp->vp_length);
return fr_dbuff_set(dbuff, &our_dbuff);
}
+static ssize_t fr_der_encode_ipv4_addr(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
+{
+ fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
+ fr_pair_t const *vp;
+
+ vp = fr_dcursor_current(cursor);
+ PAIR_VERIFY(vp);
+ fr_assert(!vp->da->flags.is_raw);
+
+ /*
+ * RFC3779 Section 2.1.1.
+ *
+ * An IP address or prefix is encoded in the IP address delegation
+ * extension as a DER-encoded ASN.1 BIT STRING containing the constant
+ * most-significant bits. Recall [X.690] that the DER encoding of a BIT
+ * STRING consists of the BIT STRING type (0x03), followed by (an
+ * encoding of) the number of value octets, followed by the value. The
+ * value consists of an "initial octet" that specifies the number of
+ * unused bits in the last value octet, followed by the "subsequent
+ * octets" that contain the octets of the bit string. (For IP
+ * addresses, the encoding of the length will be just the length.)
+ */
+
+ /*
+ * The number of unused bits in the last byte is always zero.
+ */
+ FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) 0x00);
+ FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv4addr, sizeof(vp->vp_ipv4addr));
+
+ return fr_dbuff_set(dbuff, &our_dbuff);
+}
+
+static ssize_t fr_der_encode_ipv6_addr(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
+{
+ fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
+ fr_pair_t const *vp;
+
+ vp = fr_dcursor_current(cursor);
+ PAIR_VERIFY(vp);
+ fr_assert(!vp->da->flags.is_raw);
+
+ /*
+ * RFC3779 Section 2.1.1.
+ *
+ * An IP address or prefix is encoded in the IP address delegation
+ * extension as a DER-encoded ASN.1 BIT STRING containing the constant
+ * most-significant bits. Recall [X.690] that the DER encoding of a BIT
+ * STRING consists of the BIT STRING type (0x03), followed by (an
+ * encoding of) the number of value octets, followed by the value. The
+ * value consists of an "initial octet" that specifies the number of
+ * unused bits in the last value octet, followed by the "subsequent
+ * octets" that contain the octets of the bit string. (For IP
+ * addresses, the encoding of the length will be just the length.)
+ */
+
+ /*
+ * The number of unused bits in the last byte is always zero.
+ */
+ FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) 0x00);
+ FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
+
+ return fr_dbuff_set(dbuff, &our_dbuff);
+}
+
+
+
static ssize_t fr_der_encode_octetstring(fr_dbuff_t *dbuff, fr_dcursor_t *cursor,
UNUSED fr_der_encode_ctx_t *encode_ctx)
{
return fr_dbuff_set(dbuff, &our_dbuff);
}
+
static ssize_t fr_der_encode_null(UNUSED fr_dbuff_t *dbuff, fr_dcursor_t *cursor,
UNUSED fr_der_encode_ctx_t *encode_ctx)
{
return fr_dbuff_set(dbuff, &our_dbuff);
}
+static const fr_der_tag_encode_t tag_funcs[FR_DER_TAG_MAX] = {
+ [FR_DER_TAG_BOOLEAN] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_boolean },
+ [FR_DER_TAG_INTEGER] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_integer },
+ [FR_DER_TAG_BITSTRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_bitstring },
+ [FR_DER_TAG_OCTETSTRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_octetstring },
+ [FR_DER_TAG_NULL] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_null },
+ [FR_DER_TAG_OID] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_oid },
+ [FR_DER_TAG_ENUMERATED] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_enumerated },
+ [FR_DER_TAG_UTF8_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
+ [FR_DER_TAG_SEQUENCE] = { .constructed = FR_DER_TAG_CONSTRUCTED, .encode = fr_der_encode_sequence },
+ [FR_DER_TAG_SET] = { .constructed = FR_DER_TAG_CONSTRUCTED, .encode = fr_der_encode_set },
+ [FR_DER_TAG_PRINTABLE_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE,
+ .encode = fr_der_encode_string },
+ [FR_DER_TAG_T61_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
+ [FR_DER_TAG_IA5_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
+ [FR_DER_TAG_UTC_TIME] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_utc_time },
+ [FR_DER_TAG_GENERALIZED_TIME] = { .constructed = FR_DER_TAG_PRIMITIVE,
+ .encode = fr_der_encode_generalized_time },
+ [FR_DER_TAG_VISIBLE_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
+ [FR_DER_TAG_GENERAL_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
+ [FR_DER_TAG_UNIVERSAL_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE,
+ .encode = fr_der_encode_string },
+};
+
+static const fr_der_tag_encode_t type_funcs[FR_TYPE_MAX] = {
+ [FR_TYPE_IPV4_ADDR] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_ipv4_addr },
+ [FR_TYPE_IPV6_ADDR] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_ipv6_addr },
+};
+
+
/** Encode the length field of a DER structure
*
* The input dbuff is composed of the following data:
fr_pair_t const *vp;
fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
fr_dbuff_marker_t marker, encoding_start;
- fr_der_tag_encode_t *func;
+ fr_der_tag_encode_t const *func;
fr_der_tag_t tag;
fr_der_tag_class_t tag_class;
fr_der_encode_ctx_t *uctx = encode_ctx;
fr_assert(tag < FR_DER_TAG_MAX);
- func = &tag_funcs[tag];
- if (!func->encode) {
- fr_strerror_printf("No encoding function for type %s", fr_type_to_str(vp->vp_type));
- return -1;
+ switch (vp->vp_type) {
+ case FR_TYPE_IPV4_ADDR:
+ case FR_TYPE_IPV6_ADDR:
+ func = &type_funcs[tag];
+ break;
+
+ default:
+ func = &tag_funcs[tag];
+ break;
}
+ fr_assert(func->encode != NULL);
/*
* Default flag class is 0, which is FR_DER_CLASS_UNIVERSAL.
encode-pair Issuer = { RelativeDistinguishedName = { AttributeTypeAndValue = { joint-iso-itu-t = { ds = { attributeType = { organizationName = "Digital Signature Trust Co." } } } } }, RelativeDistinguishedName = { AttributeTypeAndValue = { joint-iso-itu-t = { ds = { attributeType = { commonName = "DST Root CA X3" } } } } } }
match 30 3f 31 24 30 22 06 03 55 04 0a 13 1b 44 69 67 69 74 61 6c 20 53 69 67 6e 61 74 75 72 65 20 54 72 75 73 74 20 43 6f 2e 31 17 30 15 06 03 55 04 03 13 0e 44 53 54 20 52 6f 6f 74 20 43 41 20 58 33
+proto-dictionary der
+
+encode-pair Test-IPv4-Address = 10.5.0.4
+match 03 05 00 0a 05 00 04
+
+proto-dictionary-root Test-IPv4-Address
+
+decode-pair 03 05 00 0a 05 00 04
+match Test-IPv4-Address = 10.5.0.4
+
count
-match 529
+match 535
DEFINE Test-Integer integer
+DEFINE Test-IPv4-Address ipv4addr
+DEFINE Test-IPv6-Address ipv4addr
+
DEFINE Foo sequence sequence_of=integer
BEGIN Foo
DEFINE Test-Integer integer