0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/export.h>
0010 #include <linux/oid_registry.h>
0011 #include <linux/kernel.h>
0012 #include <linux/errno.h>
0013 #include <linux/bug.h>
0014 #include <linux/asn1.h>
0015 #include "oid_registry_data.c"
0016
0017 MODULE_DESCRIPTION("OID Registry");
0018 MODULE_AUTHOR("Red Hat, Inc.");
0019 MODULE_LICENSE("GPL");
0020
0021
0022
0023
0024
0025
0026 enum OID look_up_OID(const void *data, size_t datasize)
0027 {
0028 const unsigned char *octets = data;
0029 enum OID oid;
0030 unsigned char xhash;
0031 unsigned i, j, k, hash;
0032 size_t len;
0033
0034
0035 hash = datasize - 1;
0036
0037 for (i = 0; i < datasize; i++)
0038 hash += octets[i] * 33;
0039 hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash;
0040 hash &= 0xff;
0041
0042
0043
0044
0045
0046 i = 0;
0047 k = OID__NR;
0048 while (i < k) {
0049 j = (i + k) / 2;
0050
0051 xhash = oid_search_table[j].hash;
0052 if (xhash > hash) {
0053 k = j;
0054 continue;
0055 }
0056 if (xhash < hash) {
0057 i = j + 1;
0058 continue;
0059 }
0060
0061 oid = oid_search_table[j].oid;
0062 len = oid_index[oid + 1] - oid_index[oid];
0063 if (len > datasize) {
0064 k = j;
0065 continue;
0066 }
0067 if (len < datasize) {
0068 i = j + 1;
0069 continue;
0070 }
0071
0072
0073
0074
0075 while (len > 0) {
0076 unsigned char a = oid_data[oid_index[oid] + --len];
0077 unsigned char b = octets[len];
0078 if (a > b) {
0079 k = j;
0080 goto next;
0081 }
0082 if (a < b) {
0083 i = j + 1;
0084 goto next;
0085 }
0086 }
0087 return oid;
0088 next:
0089 ;
0090 }
0091
0092 return OID__NR;
0093 }
0094 EXPORT_SYMBOL_GPL(look_up_OID);
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 int parse_OID(const void *data, size_t datasize, enum OID *oid)
0107 {
0108 const unsigned char *v = data;
0109
0110
0111 if (datasize < 3 || v[0] != ASN1_OID || v[1] != datasize - 2)
0112 return -EBADMSG;
0113
0114 *oid = look_up_OID(data + 2, datasize - 2);
0115 return 0;
0116 }
0117 EXPORT_SYMBOL_GPL(parse_OID);
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize)
0131 {
0132 const unsigned char *v = data, *end = v + datasize;
0133 unsigned long num;
0134 unsigned char n;
0135 size_t ret;
0136 int count;
0137
0138 if (v >= end)
0139 goto bad;
0140
0141 n = *v++;
0142 ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40);
0143 if (count >= bufsize)
0144 return -ENOBUFS;
0145 buffer += count;
0146 bufsize -= count;
0147
0148 while (v < end) {
0149 num = 0;
0150 n = *v++;
0151 if (!(n & 0x80)) {
0152 num = n;
0153 } else {
0154 num = n & 0x7f;
0155 do {
0156 if (v >= end)
0157 goto bad;
0158 n = *v++;
0159 num <<= 7;
0160 num |= n & 0x7f;
0161 } while (n & 0x80);
0162 }
0163 ret += count = snprintf(buffer, bufsize, ".%lu", num);
0164 if (count >= bufsize)
0165 return -ENOBUFS;
0166 buffer += count;
0167 bufsize -= count;
0168 }
0169
0170 return ret;
0171
0172 bad:
0173 snprintf(buffer, bufsize, "(bad)");
0174 return -EBADMSG;
0175 }
0176 EXPORT_SYMBOL_GPL(sprint_oid);
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187 int sprint_OID(enum OID oid, char *buffer, size_t bufsize)
0188 {
0189 int ret;
0190
0191 BUG_ON(oid >= OID__NR);
0192
0193 ret = sprint_oid(oid_data + oid_index[oid],
0194 oid_index[oid + 1] - oid_index[oid],
0195 buffer, bufsize);
0196 BUG_ON(ret == -EBADMSG);
0197 return ret;
0198 }
0199 EXPORT_SYMBOL_GPL(sprint_OID);