Branch data Line data Source code
1 : : /* ASN.1 Object identifier (OID) registry
2 : : *
3 : : * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
4 : : * Written by David Howells (dhowells@redhat.com)
5 : : *
6 : : * This program is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU General Public Licence
8 : : * as published by the Free Software Foundation; either version
9 : : * 2 of the Licence, or (at your option) any later version.
10 : : */
11 : :
12 : : #include <linux/module.h>
13 : : #include <linux/export.h>
14 : : #include <linux/oid_registry.h>
15 : : #include <linux/kernel.h>
16 : : #include <linux/errno.h>
17 : : #include <linux/bug.h>
18 : : #include "oid_registry_data.c"
19 : :
20 : : MODULE_DESCRIPTION("OID Registry");
21 : : MODULE_AUTHOR("Red Hat, Inc.");
22 : : MODULE_LICENSE("GPL");
23 : :
24 : : /**
25 : : * look_up_OID - Find an OID registration for the specified data
26 : : * @data: Binary representation of the OID
27 : : * @datasize: Size of the binary representation
28 : : */
29 : 0 : enum OID look_up_OID(const void *data, size_t datasize)
30 : : {
31 : : const unsigned char *octets = data;
32 : : enum OID oid;
33 : : unsigned char xhash;
34 : : unsigned i, j, k, hash;
35 : : size_t len;
36 : :
37 : : /* Hash the OID data */
38 : 0 : hash = datasize - 1;
39 : :
40 [ # # ]: 0 : for (i = 0; i < datasize; i++)
41 : 0 : hash += octets[i] * 33;
42 : 0 : hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash;
43 : 0 : hash &= 0xff;
44 : :
45 : : /* Binary search the OID registry. OIDs are stored in ascending order
46 : : * of hash value then ascending order of size and then in ascending
47 : : * order of reverse value.
48 : : */
49 : : i = 0;
50 : : k = OID__NR;
51 [ # # ]: 0 : while (i < k) {
52 : 0 : j = (i + k) / 2;
53 : :
54 : 0 : xhash = oid_search_table[j].hash;
55 [ # # ]: 0 : if (xhash > hash) {
56 : : k = j;
57 : 0 : continue;
58 : : }
59 [ # # ]: 0 : if (xhash < hash) {
60 : 0 : i = j + 1;
61 : 0 : continue;
62 : : }
63 : :
64 : 0 : oid = oid_search_table[j].oid;
65 : 0 : len = oid_index[oid + 1] - oid_index[oid];
66 [ # # ]: 0 : if (len > datasize) {
67 : : k = j;
68 : 0 : continue;
69 : : }
70 [ # # ]: 0 : if (len < datasize) {
71 : 0 : i = j + 1;
72 : 0 : continue;
73 : : }
74 : :
75 : : /* Variation is most likely to be at the tail end of the
76 : : * OID, so do the comparison in reverse.
77 : : */
78 [ # # ]: 0 : while (len > 0) {
79 : 0 : unsigned char a = oid_data[oid_index[oid] + --len];
80 : 0 : unsigned char b = octets[len];
81 [ # # ]: 0 : if (a > b) {
82 : : k = j;
83 : : goto next;
84 : : }
85 [ # # ]: 0 : if (a < b) {
86 : 0 : i = j + 1;
87 : 0 : goto next;
88 : : }
89 : : }
90 : : return oid;
91 : : next:
92 : : ;
93 : : }
94 : :
95 : : return OID__NR;
96 : : }
97 : : EXPORT_SYMBOL_GPL(look_up_OID);
98 : :
99 : : /*
100 : : * sprint_OID - Print an Object Identifier into a buffer
101 : : * @data: The encoded OID to print
102 : : * @datasize: The size of the encoded OID
103 : : * @buffer: The buffer to render into
104 : : * @bufsize: The size of the buffer
105 : : *
106 : : * The OID is rendered into the buffer in "a.b.c.d" format and the number of
107 : : * bytes is returned. -EBADMSG is returned if the data could not be intepreted
108 : : * and -ENOBUFS if the buffer was too small.
109 : : */
110 : 0 : int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize)
111 : : {
112 : 0 : const unsigned char *v = data, *end = v + datasize;
113 : : unsigned long num;
114 : : unsigned char n;
115 : : size_t ret;
116 : : int count;
117 : :
118 [ # # ]: 0 : if (v >= end)
119 : : return -EBADMSG;
120 : :
121 : 0 : n = *v++;
122 : 0 : ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40);
123 : 0 : buffer += count;
124 : 0 : bufsize -= count;
125 [ # # ]: 0 : if (bufsize == 0)
126 : : return -ENOBUFS;
127 : :
128 [ # # ]: 0 : while (v < end) {
129 : : num = 0;
130 : 0 : n = *v++;
131 [ # # ]: 0 : if (!(n & 0x80)) {
132 : 0 : num = n;
133 : : } else {
134 : 0 : num = n & 0x7f;
135 : : do {
136 [ # # ]: 0 : if (v >= end)
137 : : return -EBADMSG;
138 : 0 : n = *v++;
139 : 0 : num <<= 7;
140 : 0 : num |= n & 0x7f;
141 [ # # ]: 0 : } while (n & 0x80);
142 : : }
143 : 0 : ret += count = snprintf(buffer, bufsize, ".%lu", num);
144 : 0 : buffer += count;
145 : 0 : bufsize -= count;
146 [ # # ]: 0 : if (bufsize == 0)
147 : : return -ENOBUFS;
148 : : }
149 : :
150 : 0 : return ret;
151 : : }
152 : : EXPORT_SYMBOL_GPL(sprint_oid);
153 : :
154 : : /**
155 : : * sprint_OID - Print an Object Identifier into a buffer
156 : : * @oid: The OID to print
157 : : * @buffer: The buffer to render into
158 : : * @bufsize: The size of the buffer
159 : : *
160 : : * The OID is rendered into the buffer in "a.b.c.d" format and the number of
161 : : * bytes is returned.
162 : : */
163 : 0 : int sprint_OID(enum OID oid, char *buffer, size_t bufsize)
164 : : {
165 : : int ret;
166 : :
167 [ # # ]: 0 : BUG_ON(oid >= OID__NR);
168 : :
169 : 0 : ret = sprint_oid(oid_data + oid_index[oid],
170 : 0 : oid_index[oid + 1] - oid_index[oid],
171 : : buffer, bufsize);
172 [ # # ]: 0 : BUG_ON(ret == -EBADMSG);
173 : 0 : return ret;
174 : : }
175 : : EXPORT_SYMBOL_GPL(sprint_OID);
|