1 #include "oid.h"
2 
3 #include <errno.h>
4 #include "common.h"
5 #include "log.h"
6 #include "asn1/decode.h"
7 
8 void
free_arcs(struct oid_arcs * arcs)9 free_arcs(struct oid_arcs *arcs)
10 {
11 	free(arcs->arcs);
12 }
13 
14 /*
15  * Wrapper for OBJECT_IDENTIFIER_get_arcs().
16  *
17  * Callers must free @result.
18  *
19  * TODO (fine) Most of the time, this function is called to compare @result
20  * to some oid. Maybe create a wrapper that takes care of all the boilerplate.
21  */
22 int
oid2arcs(OBJECT_IDENTIFIER_t * oid,struct oid_arcs * result)23 oid2arcs(OBJECT_IDENTIFIER_t *oid, struct oid_arcs *result)
24 {
25 	static const size_t MAX_ARCS = 9;
26 	ssize_t count;
27 	ssize_t count2;
28 	asn_oid_arc_t *tmp;
29 
30 	result->arcs = malloc(MAX_ARCS * sizeof(asn_oid_arc_t));
31 	if (result->arcs == NULL)
32 		return pr_enomem();
33 
34 	count = OBJECT_IDENTIFIER_get_arcs(oid, result->arcs, MAX_ARCS);
35 	if (count < 0) {
36 		pr_val_err("OBJECT_IDENTIFIER_get_arcs() returned %zd.", count);
37 		free(result->arcs);
38 		return count;
39 	}
40 
41 	result->count = count;
42 
43 	/* If necessary, reallocate arcs array and try again. */
44 	if (count > MAX_ARCS) {
45 		tmp = realloc(result->arcs, count * sizeof(asn_oid_arc_t));
46 		if (tmp == NULL) {
47 			free(result->arcs);
48 			return pr_enomem();
49 		}
50 		result->arcs = tmp;
51 
52 		count2 = OBJECT_IDENTIFIER_get_arcs(oid, result->arcs, count);
53 		if (count != count2) {
54 			pr_val_err("OBJECT_IDENTIFIER_get_arcs() returned %zd. (expected %zd)",
55 			    count2, count);
56 			free(result->arcs);
57 			return -EINVAL;
58 		}
59 	}
60 
61 	return 0;
62 }
63 
oid_equal(OBJECT_IDENTIFIER_t * a,OBJECT_IDENTIFIER_t * b)64 bool oid_equal(OBJECT_IDENTIFIER_t *a, OBJECT_IDENTIFIER_t *b)
65 {
66 	return (a->size == b->size) && (memcmp(a->buf, b->buf, a->size) == 0);
67 }
68 
__arcs_equal(asn_oid_arc_t const * a,size_t a_count,asn_oid_arc_t const * b,size_t b_count)69 static bool __arcs_equal(asn_oid_arc_t const *a, size_t a_count,
70     asn_oid_arc_t const *b, size_t b_count)
71 {
72 	long int i;
73 
74 	if (a_count != b_count)
75 		return false;
76 
77 	/* Most OIDs start with the same numbers, so iterate backwards. */
78 	for (i = a_count - 1; i >= 0; i--) {
79 		if (a[i] != b[i])
80 			return false;
81 	}
82 
83 	return true;
84 }
85 
arcs_equal(struct oid_arcs const * a,struct oid_arcs const * b)86 bool arcs_equal(struct oid_arcs const *a, struct oid_arcs const *b)
87 {
88 	return __arcs_equal(a->arcs, a->count, b->arcs, b->count);
89 }
90 
arcs_equal_oids(struct oid_arcs * arcs,asn_oid_arc_t const * oids,size_t oids_len)91 bool arcs_equal_oids(struct oid_arcs *arcs, asn_oid_arc_t const *oids,
92     size_t oids_len)
93 {
94 	return __arcs_equal(arcs->arcs, arcs->count, oids, oids_len);
95 }
96