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