brintos

brintos / linux-shallow public Read only

0
0
Text · 4.7 KiB · 8267e8d Raw
209 lines · plain
1#!/usr/bin/perl -w2# SPDX-License-Identifier: GPL-2.0-or-later3#4# Build a static ASN.1 Object Identified (OID) registry5#6# Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.7# Written by David Howells (dhowells@redhat.com)8#9 10use strict;11use Cwd qw(abs_path);12 13my @names = ();14my @oids = ();15 16if ($#ARGV != 1) {17    print STDERR "Format: ", $0, " <in-h-file> <out-c-file>\n";18    exit(2);19}20 21my $abs_srctree = abs_path($ENV{'srctree'});22 23#24# Open the file to read from25#26open IN_FILE, "<$ARGV[0]" || die;27while (<IN_FILE>) {28    chomp;29    if (m!\s+OID_([a-zA-z][a-zA-Z0-9_]+),\s+/[*]\s+([012][.0-9]*)\s+[*]/!) {30	push @names, $1;31	push @oids, $2;32    }33}34close IN_FILE || die;35 36#37# Open the files to write into38#39open C_FILE, ">$ARGV[1]" or die;40print C_FILE "/*\n";41my $scriptname = $0;42$scriptname =~ s#^\Q$abs_srctree/\E##;43print C_FILE " * Automatically generated by ", $scriptname, ".  Do not edit\n";44print C_FILE " */\n";45 46#47# Split the data up into separate lists and also determine the lengths of the48# encoded data arrays.49#50my @indices = ();51my @lengths = ();52my $total_length = 0;53 54for (my $i = 0; $i <= $#names; $i++) {55    my $name = $names[$i];56    my $oid = $oids[$i];57 58    my @components = split(/[.]/, $oid);59 60    # Determine the encoded length of this OID61    my $size = $#components;62    for (my $loop = 2; $loop <= $#components; $loop++) {63	my $c = $components[$loop];64 65	# We will base128 encode the number66	my $tmp = ($c == 0) ? 0 : int(log($c)/log(2));67	$tmp = int($tmp / 7);68	$size += $tmp;69    }70    push @lengths, $size;71    push @indices, $total_length;72    $total_length += $size;73}74 75#76# Emit the look-up-by-OID index table77#78print C_FILE "\n";79if ($total_length <= 255) {80    print C_FILE "static const unsigned char oid_index[OID__NR + 1] = {\n";81} else {82    print C_FILE "static const unsigned short oid_index[OID__NR + 1] = {\n";83}84for (my $i = 0; $i <= $#names; $i++) {85    print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n"86}87print C_FILE "\t[OID__NR] = ", $total_length, "\n";88print C_FILE "};\n";89 90#91# Encode the OIDs92#93my @encoded_oids = ();94 95for (my $i = 0; $i <= $#names; $i++) {96    my @octets = ();97 98    my @components = split(/[.]/, $oids[$i]);99 100    push @octets, $components[0] * 40 + $components[1];101 102    for (my $loop = 2; $loop <= $#components; $loop++) {103	my $c = $components[$loop];104 105	# Base128 encode the number106	my $tmp = ($c == 0) ? 0 : int(log($c)/log(2));107	$tmp = int($tmp / 7);108 109	for (; $tmp > 0; $tmp--) {110	    push @octets, (($c >> $tmp * 7) & 0x7f) | 0x80;111	}112	push @octets, $c & 0x7f;113    }114 115    push @encoded_oids, \@octets;116}117 118#119# Create a hash value for each OID120#121my @hash_values = ();122for (my $i = 0; $i <= $#names; $i++) {123    my @octets = @{$encoded_oids[$i]};124 125    my $hash = $#octets;126    foreach (@octets) {127	$hash += $_ * 33;128    }129 130    $hash = ($hash >> 24) ^ ($hash >> 16) ^ ($hash >> 8) ^ ($hash);131 132    push @hash_values, $hash & 0xff;133}134 135#136# Emit the OID data137#138print C_FILE "\n";139print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n";140for (my $i = 0; $i <= $#names; $i++) {141    my @octets = @{$encoded_oids[$i]};142    print C_FILE "\t";143    print C_FILE $_, ", " foreach (@octets);144    print C_FILE "\t// ", $names[$i];145    print C_FILE "\n";146}147print C_FILE "};\n";148 149#150# Build the search index table (ordered by length then hash then content)151#152my @index_table = ( 0 .. $#names );153 154@index_table = sort {155    my @octets_a = @{$encoded_oids[$a]};156    my @octets_b = @{$encoded_oids[$b]};157 158    return $hash_values[$a] <=> $hash_values[$b]159	if ($hash_values[$a] != $hash_values[$b]);160    return $#octets_a <=> $#octets_b161	if ($#octets_a != $#octets_b);162    for (my $i = $#octets_a; $i >= 0; $i--) {163	return $octets_a[$i] <=> $octets_b[$i]164	    if ($octets_a[$i] != $octets_b[$i]);165    }166    return 0;167 168} @index_table;169 170#171# Emit the search index and hash value table172#173print C_FILE "\n";174print C_FILE "static const struct {\n";175print C_FILE "\tunsigned char hash;\n";176if ($#names <= 255) {177    print C_FILE "\tenum OID oid : 8;\n";178} else {179    print C_FILE "\tenum OID oid : 16;\n";180}181print C_FILE "} oid_search_table[OID__NR] = {\n";182for (my $i = 0; $i <= $#names; $i++) {183    my @octets = @{$encoded_oids[$index_table[$i]]};184    printf(C_FILE "\t[%3u] = { %3u, OID_%-35s }, // ",185	   $i,186	   $hash_values[$index_table[$i]],187	   $names[$index_table[$i]]);188    printf C_FILE "%02x", $_ foreach (@octets);189    print C_FILE "\n";190}191print C_FILE "};\n";192 193#194# Emit the OID debugging name table195#196#print C_FILE "\n";197#print C_FILE "const char *const oid_name_table[OID__NR + 1] = {\n";198#199#for (my $i = 0; $i <= $#names; $i++) {200#    print C_FILE "\t\"", $names[$i], "\",\n"201#}202#print C_FILE "\t\"Unknown-OID\"\n";203#print C_FILE "};\n";204 205#206# Polish off207#208close C_FILE or die;209