Branch data Line data Source code
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 : 4347 : 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 : 4347 : hash = datasize - 1; 35 : : 36 [ + + ]: 37260 : for (i = 0; i < datasize; i++) 37 : 32913 : hash += octets[i] * 33; 38 : 4347 : hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash; 39 : 4347 : 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 [ + - ]: 25875 : while (i < k) { 48 : 21528 : j = (i + k) / 2; 49 : : 50 : 21528 : xhash = oid_search_table[j].hash; 51 [ + + ]: 21528 : if (xhash > hash) { 52 : : k = j; 53 : 8694 : continue; 54 : : } 55 [ + + ]: 12834 : if (xhash < hash) { 56 : 8073 : i = j + 1; 57 : 8073 : continue; 58 : : } 59 : : 60 : 4761 : oid = oid_search_table[j].oid; 61 : 4761 : len = oid_index[oid + 1] - oid_index[oid]; 62 [ - + ]: 4761 : if (len > datasize) { 63 : : k = j; 64 : 0 : continue; 65 : : } 66 [ - + ]: 4761 : if (len < datasize) { 67 : 0 : i = j + 1; 68 : 0 : 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 [ + + ]: 37674 : while (len > 0) { 75 : 33327 : unsigned char a = oid_data[oid_index[oid] + --len]; 76 : 33327 : unsigned char b = octets[len]; 77 [ + + ]: 33327 : if (a > b) { 78 : : k = j; 79 : : goto next; 80 : : } 81 [ + - ]: 32913 : if (a < b) { 82 : 0 : i = j + 1; 83 : 0 : goto next; 84 : : } 85 : : } 86 : 4347 : 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 : 0 : int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) 107 : : { 108 : 0 : 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 [ # # ]: 0 : if (v >= end) 115 : : goto bad; 116 : : 117 : 0 : n = *v++; 118 : 0 : ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); 119 [ # # ]: 0 : if (count >= bufsize) 120 : : return -ENOBUFS; 121 : 0 : buffer += count; 122 : 0 : bufsize -= count; 123 : : 124 [ # # ]: 0 : while (v < end) { 125 : : num = 0; 126 : 0 : n = *v++; 127 [ # # ]: 0 : if (!(n & 0x80)) { 128 : 0 : num = n; 129 : : } else { 130 : 0 : num = n & 0x7f; 131 : : do { 132 [ # # ]: 0 : if (v >= end) 133 : : goto bad; 134 : 0 : n = *v++; 135 : 0 : num <<= 7; 136 : 0 : num |= n & 0x7f; 137 [ # # ]: 0 : } while (n & 0x80); 138 : : } 139 : 0 : ret += count = snprintf(buffer, bufsize, ".%lu", num); 140 [ # # ]: 0 : if (count >= bufsize) 141 : : return -ENOBUFS; 142 : 0 : buffer += count; 143 : 0 : bufsize -= count; 144 : : } 145 : : 146 : 0 : return ret; 147 : : 148 : : bad: 149 : 0 : snprintf(buffer, bufsize, "(bad)"); 150 : 0 : 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 : 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);