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