blob: b5c346a5233a37a35b3339f970ccaa8d02035872 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001/*-
2 * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
5#include <RELATIVE-OID.h>
Lev Walkin0787ff02004-06-17 23:43:39 +00006#include <limits.h> /* for CHAR_BIT */
Lev Walkinf15320b2004-06-03 03:38:44 +00007#include <assert.h>
8#include <errno.h>
9
10/*
11 * RELATIVE-OID basic type description.
12 */
13static ber_tlv_tag_t asn1_DEF_RELATIVE_OID_tags[] = {
14 (ASN_TAG_CLASS_UNIVERSAL | (13 << 2))
15};
16asn1_TYPE_descriptor_t asn1_DEF_RELATIVE_OID = {
17 "RELATIVE-OID",
18 asn_generic_no_constraint,
19 INTEGER_decode_ber, /* Implemented in terms of INTEGER type */
20 OBJECT_IDENTIFIER_encode_der,
21 RELATIVE_OID_print,
22 INTEGER_free,
23 0, /* Use generic outmost tag fetcher */
24 asn1_DEF_RELATIVE_OID_tags,
25 sizeof(asn1_DEF_RELATIVE_OID_tags)
26 / sizeof(asn1_DEF_RELATIVE_OID_tags[0]),
27 1, /* Single UNIVERSAL tag may be implicitly overriden */
Lev Walkind9bd7752004-06-05 08:17:50 +000028 0, /* Always in primitive form */
29 0 /* No specifics */
Lev Walkinf15320b2004-06-03 03:38:44 +000030};
31
32int
33RELATIVE_OID_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
34 asn_app_consume_bytes_f *cb, void *app_key) {
35 const RELATIVE_OID_t *st = sptr;
36 int startn;
37 int i;
38
Lev Walkind9bd7752004-06-05 08:17:50 +000039 (void)td; /* Unused argument */
40 (void)ilevel; /* Unused argument */
41
Lev Walkinf15320b2004-06-03 03:38:44 +000042 if(!st || !st->buf)
43 return cb("<absent>", 8, app_key);
44
45 /* Dump preamble */
46 if(cb("{ ", 2, app_key))
47 return -1;
48
49 for(i = 0, startn = 0; i < st->size; i++) {
50 uint8_t b = st->buf[i];
51 if((b & 0x80)) /* Continuation expected */
52 continue;
53 if(startn && cb(" ", 1, app_key)) /* Separate arcs */
54 return -1;
55 if(OBJECT_IDENTIFIER_print_arc(&st->buf[startn],
56 i - startn + 1, 0, cb, app_key))
57 return -1;
58 startn = i + 1;
59 }
60
61 return cb(" }", 2, app_key);
62}
63
64
65int
Lev Walkin29a044b2004-06-14 07:24:36 +000066RELATIVE_OID_get_arcs(RELATIVE_OID_t *roid,
67 void *arcs, unsigned int arc_type_size, unsigned int arc_slots) {
68 void *arcs_end = arcs + (arc_slots * arc_type_size);
69 int num_arcs = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000070 int startn = 0;
71 int i;
72
73 if(!roid || !roid->buf) {
74 errno = EINVAL;
75 return -1;
76 }
77
78 for(i = 0; i < roid->size; i++) {
79 uint8_t b = roid->buf[i];
80 if((b & 0x80)) /* Continuation expected */
81 continue;
82
Lev Walkin29a044b2004-06-14 07:24:36 +000083 if(arcs < arcs_end) {
84 if(OBJECT_IDENTIFIER_get_single_arc(
85 &roid->buf[startn],
86 i - startn + 1, 0,
87 arcs, arc_type_size))
Lev Walkinf15320b2004-06-03 03:38:44 +000088 return -1;
Lev Walkin29a044b2004-06-14 07:24:36 +000089 arcs += arc_type_size;
90 num_arcs++;
Lev Walkinf15320b2004-06-03 03:38:44 +000091 }
92
93 startn = i + 1;
94 }
95
Lev Walkin29a044b2004-06-14 07:24:36 +000096 return num_arcs;
Lev Walkinf15320b2004-06-03 03:38:44 +000097}
98
99int
Lev Walkin0787ff02004-06-17 23:43:39 +0000100RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_size, unsigned int arcs_slots) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000101 uint8_t *buf;
102 uint8_t *bp;
103 int size;
104 int i;
105
Lev Walkin0787ff02004-06-17 23:43:39 +0000106 if(roid == NULL || arcs == NULL || arc_type_size < 1) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000107 errno = EINVAL;
108 return -1;
109 }
110
111 /*
112 * Roughly estimate the maximum size necessary to encode these arcs.
113 */
Lev Walkin0787ff02004-06-17 23:43:39 +0000114 size = ((arc_type_size * CHAR_BIT + 6) / 7) * arcs_slots;
Lev Walkinf15320b2004-06-03 03:38:44 +0000115 bp = buf = MALLOC(size + 1);
116 if(!buf) {
117 /* ENOMEM */
118 return -1;
119 }
120
121 /*
Lev Walkin0787ff02004-06-17 23:43:39 +0000122 * Encode the arcs.
Lev Walkinf15320b2004-06-03 03:38:44 +0000123 */
Lev Walkin0787ff02004-06-17 23:43:39 +0000124 for(i = 0; i < arcs_slots; i++, (char *)arcs += arc_type_size) {
125 bp += OBJECT_IDENTIFIER_set_single_arc(bp,
126 arcs, arc_type_size, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000127 }
128
Lev Walkin0787ff02004-06-17 23:43:39 +0000129 assert((bp - buf) <= size);
130
Lev Walkinf15320b2004-06-03 03:38:44 +0000131 /*
132 * Replace buffer.
133 */
Lev Walkin0787ff02004-06-17 23:43:39 +0000134 roid->size = bp - buf;
Lev Walkinf15320b2004-06-03 03:38:44 +0000135 bp = roid->buf;
136 roid->buf = buf;
137 if(bp) FREEMEM(bp);
138
139 return 0;
140}
Lev Walkin0787ff02004-06-17 23:43:39 +0000141