uboot/lib/oid_registry.c
<<
>>
Prefs
   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#ifdef __UBOOT__
   9#include <linux/compat.h>
  10#else
  11#include <linux/module.h>
  12#include <linux/export.h>
  13#endif
  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
  20MODULE_DESCRIPTION("OID Registry");
  21MODULE_AUTHOR("Red Hat, Inc.");
  22MODULE_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 */
  29enum 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        hash = datasize - 1;
  39
  40        for (i = 0; i < datasize; i++)
  41                hash += octets[i] * 33;
  42        hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash;
  43        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        while (i < k) {
  52                j = (i + k) / 2;
  53
  54                xhash = oid_search_table[j].hash;
  55                if (xhash > hash) {
  56                        k = j;
  57                        continue;
  58                }
  59                if (xhash < hash) {
  60                        i = j + 1;
  61                        continue;
  62                }
  63
  64                oid = oid_search_table[j].oid;
  65                len = oid_index[oid + 1] - oid_index[oid];
  66                if (len > datasize) {
  67                        k = j;
  68                        continue;
  69                }
  70                if (len < datasize) {
  71                        i = j + 1;
  72                        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                while (len > 0) {
  79                        unsigned char a = oid_data[oid_index[oid] + --len];
  80                        unsigned char b = octets[len];
  81                        if (a > b) {
  82                                k = j;
  83                                goto next;
  84                        }
  85                        if (a < b) {
  86                                i = j + 1;
  87                                goto next;
  88                        }
  89                }
  90                return oid;
  91        next:
  92                ;
  93        }
  94
  95        return OID__NR;
  96}
  97EXPORT_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 */
 110int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize)
 111{
 112        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        if (v >= end)
 119                goto bad;
 120
 121        n = *v++;
 122        ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40);
 123        if (count >= bufsize)
 124                return -ENOBUFS;
 125        buffer += count;
 126        bufsize -= count;
 127
 128        while (v < end) {
 129                num = 0;
 130                n = *v++;
 131                if (!(n & 0x80)) {
 132                        num = n;
 133                } else {
 134                        num = n & 0x7f;
 135                        do {
 136                                if (v >= end)
 137                                        goto bad;
 138                                n = *v++;
 139                                num <<= 7;
 140                                num |= n & 0x7f;
 141                        } while (n & 0x80);
 142                }
 143                ret += count = snprintf(buffer, bufsize, ".%lu", num);
 144                if (count >= bufsize)
 145                        return -ENOBUFS;
 146                buffer += count;
 147                bufsize -= count;
 148        }
 149
 150        return ret;
 151
 152bad:
 153        snprintf(buffer, bufsize, "(bad)");
 154        return -EBADMSG;
 155}
 156EXPORT_SYMBOL_GPL(sprint_oid);
 157
 158/**
 159 * sprint_OID - Print an Object Identifier into a buffer
 160 * @oid: The OID to print
 161 * @buffer: The buffer to render into
 162 * @bufsize: The size of the buffer
 163 *
 164 * The OID is rendered into the buffer in "a.b.c.d" format and the number of
 165 * bytes is returned.
 166 */
 167int sprint_OID(enum OID oid, char *buffer, size_t bufsize)
 168{
 169        int ret;
 170
 171        BUG_ON(oid >= OID__NR);
 172
 173        ret = sprint_oid(oid_data + oid_index[oid],
 174                         oid_index[oid + 1] - oid_index[oid],
 175                         buffer, bufsize);
 176        BUG_ON(ret == -EBADMSG);
 177        return ret;
 178}
 179EXPORT_SYMBOL_GPL(sprint_OID);
 180