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 : 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 : BUG_ON(ret == -EBADMSG);
173 0 : return ret;
174 : }
175 : EXPORT_SYMBOL_GPL(sprint_OID);
|