1e1051a39Sopenharmony_ci#! /usr/bin/env perl
2e1051a39Sopenharmony_ci# Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci#
4e1051a39Sopenharmony_ci# Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci# this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci# in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci# https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci
9e1051a39Sopenharmony_ciuse integer;
10e1051a39Sopenharmony_ciuse strict;
11e1051a39Sopenharmony_ciuse warnings;
12e1051a39Sopenharmony_ciuse FindBin;
13e1051a39Sopenharmony_ciuse lib "$FindBin::Bin/../../util/perl";
14e1051a39Sopenharmony_ciuse OpenSSL::copyright;
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci# Generate the DER encoding for the given OID.
17e1051a39Sopenharmony_cisub der_it
18e1051a39Sopenharmony_ci{
19e1051a39Sopenharmony_ci    # Prologue
20e1051a39Sopenharmony_ci    my ($v) = @_;
21e1051a39Sopenharmony_ci    my @a = split(/\s+/, $v);
22e1051a39Sopenharmony_ci    my $ret = pack("C*", $a[0] * 40 + $a[1]);
23e1051a39Sopenharmony_ci    shift @a;
24e1051a39Sopenharmony_ci    shift @a;
25e1051a39Sopenharmony_ci
26e1051a39Sopenharmony_ci    # Loop over rest of bytes; or in 0x80 for multi-byte numbers.
27e1051a39Sopenharmony_ci    my $t;
28e1051a39Sopenharmony_ci    foreach (@a) {
29e1051a39Sopenharmony_ci        my @r = ();
30e1051a39Sopenharmony_ci        $t = 0;
31e1051a39Sopenharmony_ci        while ($_ >= 128) {
32e1051a39Sopenharmony_ci            my $x = $_ % 128;
33e1051a39Sopenharmony_ci            $_ /= 128;
34e1051a39Sopenharmony_ci            push(@r, ($t++ ? 0x80 : 0) | $x);
35e1051a39Sopenharmony_ci        }
36e1051a39Sopenharmony_ci        push(@r, ($t++ ? 0x80 : 0) | $_);
37e1051a39Sopenharmony_ci        $ret .= pack("C*", reverse(@r));
38e1051a39Sopenharmony_ci    }
39e1051a39Sopenharmony_ci    return $ret;
40e1051a39Sopenharmony_ci}
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_ci# The year the output file is generated.
43e1051a39Sopenharmony_cimy $YEAR = OpenSSL::copyright::latest(($0, $ARGV[0]));
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_ci# Read input, parse all #define's into OID name and value.
46e1051a39Sopenharmony_ci# Populate %ln and %sn with long and short names (%dupln and %dupsn)
47e1051a39Sopenharmony_ci# are used to watch for duplicates.  Also %nid and %obj get the
48e1051a39Sopenharmony_ci# NID and OBJ entries.
49e1051a39Sopenharmony_cimy %ln;
50e1051a39Sopenharmony_cimy %sn;
51e1051a39Sopenharmony_cimy %dupln;
52e1051a39Sopenharmony_cimy %dupsn;
53e1051a39Sopenharmony_cimy %nid;
54e1051a39Sopenharmony_cimy %obj;
55e1051a39Sopenharmony_cimy %objd;
56e1051a39Sopenharmony_ciopen(IN, "$ARGV[0]") || die "Can't open input file $ARGV[0], $!";
57e1051a39Sopenharmony_ciwhile (<IN>) {
58e1051a39Sopenharmony_ci    next unless /^\#define\s+(\S+)\s+(.*)$/;
59e1051a39Sopenharmony_ci    my $v = $1;
60e1051a39Sopenharmony_ci    my $d = $2;
61e1051a39Sopenharmony_ci    $d =~ s/^\"//;
62e1051a39Sopenharmony_ci    $d =~ s/\"$//;
63e1051a39Sopenharmony_ci    if ($v =~ /^SN_(.*)$/) {
64e1051a39Sopenharmony_ci        if (defined $dupsn{$d}) {
65e1051a39Sopenharmony_ci            print "WARNING: Duplicate short name \"$d\"\n";
66e1051a39Sopenharmony_ci        } else {
67e1051a39Sopenharmony_ci            $dupsn{$d} = 1;
68e1051a39Sopenharmony_ci        }
69e1051a39Sopenharmony_ci        $sn{$1} = $d;
70e1051a39Sopenharmony_ci    }
71e1051a39Sopenharmony_ci    elsif ($v =~ /^LN_(.*)$/) {
72e1051a39Sopenharmony_ci        if (defined $dupln{$d}) {
73e1051a39Sopenharmony_ci            print "WARNING: Duplicate long name \"$d\"\n";
74e1051a39Sopenharmony_ci        } else {
75e1051a39Sopenharmony_ci            $dupln{$d} = 1;
76e1051a39Sopenharmony_ci        }
77e1051a39Sopenharmony_ci        $ln{$1} = $d;
78e1051a39Sopenharmony_ci    }
79e1051a39Sopenharmony_ci    elsif ($v =~ /^NID_(.*)$/) {
80e1051a39Sopenharmony_ci        $nid{$d} = $1;
81e1051a39Sopenharmony_ci    }
82e1051a39Sopenharmony_ci    elsif ($v =~ /^OBJ_(.*)$/) {
83e1051a39Sopenharmony_ci        $obj{$1} = $v;
84e1051a39Sopenharmony_ci        $objd{$v} = $d;
85e1051a39Sopenharmony_ci    }
86e1051a39Sopenharmony_ci}
87e1051a39Sopenharmony_ciclose IN;
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ci# For every value in %obj, recursively expand OBJ_xxx values.  That is:
90e1051a39Sopenharmony_ci#     #define OBJ_iso 1L
91e1051a39Sopenharmony_ci#     #define OBJ_identified_organization OBJ_iso,3L
92e1051a39Sopenharmony_ci# Modify %objd values in-place.  Create an %objn array that has
93e1051a39Sopenharmony_cimy $changed;
94e1051a39Sopenharmony_cido {
95e1051a39Sopenharmony_ci    $changed = 0;
96e1051a39Sopenharmony_ci    foreach my $k (keys %objd) {
97e1051a39Sopenharmony_ci        $changed = 1 if $objd{$k} =~ s/(OBJ_[^,]+),/$objd{$1},/;
98e1051a39Sopenharmony_ci    }
99e1051a39Sopenharmony_ci} while ($changed);
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_cimy @a = sort { $a <=> $b } keys %nid;
102e1051a39Sopenharmony_cimy $n = $a[$#a] + 1;
103e1051a39Sopenharmony_cimy @lvalues = ();
104e1051a39Sopenharmony_cimy $lvalues = 0;
105e1051a39Sopenharmony_ci
106e1051a39Sopenharmony_ci# Scan all defined objects, building up the @out array.
107e1051a39Sopenharmony_ci# %obj_der holds the DER encoding as an array of bytes, and %obj_len
108e1051a39Sopenharmony_ci# holds the length in bytes.
109e1051a39Sopenharmony_cimy @out;
110e1051a39Sopenharmony_cimy %obj_der;
111e1051a39Sopenharmony_cimy %obj_len;
112e1051a39Sopenharmony_cifor (my $i = 0; $i < $n; $i++) {
113e1051a39Sopenharmony_ci    if (!defined $nid{$i}) {
114e1051a39Sopenharmony_ci        push(@out, "    { NULL, NULL, NID_undef },\n");
115e1051a39Sopenharmony_ci        next;
116e1051a39Sopenharmony_ci    }
117e1051a39Sopenharmony_ci
118e1051a39Sopenharmony_ci    my $sn = defined $sn{$nid{$i}} ? "$sn{$nid{$i}}" : "NULL";
119e1051a39Sopenharmony_ci    my $ln = defined $ln{$nid{$i}} ? "$ln{$nid{$i}}" : "NULL";
120e1051a39Sopenharmony_ci    if ($sn eq "NULL") {
121e1051a39Sopenharmony_ci        $sn = $ln;
122e1051a39Sopenharmony_ci        $sn{$nid{$i}} = $ln;
123e1051a39Sopenharmony_ci    }
124e1051a39Sopenharmony_ci    if ($ln eq "NULL") {
125e1051a39Sopenharmony_ci        $ln = $sn;
126e1051a39Sopenharmony_ci        $ln{$nid{$i}} = $sn;
127e1051a39Sopenharmony_ci    }
128e1051a39Sopenharmony_ci
129e1051a39Sopenharmony_ci    my $out = "    {\"$sn\", \"$ln\", NID_$nid{$i}";
130e1051a39Sopenharmony_ci    if (defined $obj{$nid{$i}} && $objd{$obj{$nid{$i}}} =~ /,/) {
131e1051a39Sopenharmony_ci        my $v = $objd{$obj{$nid{$i}}};
132e1051a39Sopenharmony_ci        $v =~ s/L//g;
133e1051a39Sopenharmony_ci        $v =~ s/,/ /g;
134e1051a39Sopenharmony_ci        my $r = &der_it($v);
135e1051a39Sopenharmony_ci        my $z = "";
136e1051a39Sopenharmony_ci        my $length = 0;
137e1051a39Sopenharmony_ci        # Format using fixed-with because we use strcmp later.
138e1051a39Sopenharmony_ci        foreach (unpack("C*",$r)) {
139e1051a39Sopenharmony_ci            $z .= sprintf("0x%02X,", $_);
140e1051a39Sopenharmony_ci            $length++;
141e1051a39Sopenharmony_ci        }
142e1051a39Sopenharmony_ci        $obj_der{$obj{$nid{$i}}} = $z;
143e1051a39Sopenharmony_ci        $obj_len{$obj{$nid{$i}}} = $length;
144e1051a39Sopenharmony_ci
145e1051a39Sopenharmony_ci        push(@lvalues,
146e1051a39Sopenharmony_ci            sprintf("    %-45s  /* [%5d] %s */\n",
147e1051a39Sopenharmony_ci                $z, $lvalues, $obj{$nid{$i}}));
148e1051a39Sopenharmony_ci        $out .= ", $length, &so[$lvalues]";
149e1051a39Sopenharmony_ci        $lvalues += $length;
150e1051a39Sopenharmony_ci    }
151e1051a39Sopenharmony_ci    $out .= "},\n";
152e1051a39Sopenharmony_ci    push(@out, $out);
153e1051a39Sopenharmony_ci}
154e1051a39Sopenharmony_ci
155e1051a39Sopenharmony_ci# Finally ready to generate the output.
156e1051a39Sopenharmony_ciprint <<"EOF";
157e1051a39Sopenharmony_ci/*
158e1051a39Sopenharmony_ci * WARNING: do not edit!
159e1051a39Sopenharmony_ci * Generated by crypto/objects/obj_dat.pl
160e1051a39Sopenharmony_ci *
161e1051a39Sopenharmony_ci * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
162e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
163e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
164e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
165e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
166e1051a39Sopenharmony_ci */
167e1051a39Sopenharmony_ci
168e1051a39Sopenharmony_ciEOF
169e1051a39Sopenharmony_ci
170e1051a39Sopenharmony_ciprint "/* Serialized OID's */\n";
171e1051a39Sopenharmony_ciprintf "static const unsigned char so[%d] = {\n", $lvalues + 1;
172e1051a39Sopenharmony_ciprint @lvalues;
173e1051a39Sopenharmony_ciprint "};\n\n";
174e1051a39Sopenharmony_ci
175e1051a39Sopenharmony_ciprintf "#define NUM_NID %d\n", $n;
176e1051a39Sopenharmony_ciprintf "static const ASN1_OBJECT nid_objs[NUM_NID] = {\n";
177e1051a39Sopenharmony_ciprint @out;
178e1051a39Sopenharmony_ciprint  "};\n\n";
179e1051a39Sopenharmony_ci
180e1051a39Sopenharmony_ci{
181e1051a39Sopenharmony_ci    no warnings "uninitialized";
182e1051a39Sopenharmony_ci    @a = grep(defined $sn{$nid{$_}}, 0 .. $n);
183e1051a39Sopenharmony_ci}
184e1051a39Sopenharmony_ciprintf "#define NUM_SN %d\n", $#a + 1;
185e1051a39Sopenharmony_ciprintf "static const unsigned int sn_objs[NUM_SN] = {\n";
186e1051a39Sopenharmony_ciforeach (sort { $sn{$nid{$a}} cmp $sn{$nid{$b}} } @a) {
187e1051a39Sopenharmony_ci    printf "    %4d,    /* \"$sn{$nid{$_}}\" */\n", $_;
188e1051a39Sopenharmony_ci}
189e1051a39Sopenharmony_ciprint  "};\n\n";
190e1051a39Sopenharmony_ci
191e1051a39Sopenharmony_ci{
192e1051a39Sopenharmony_ci    no warnings "uninitialized";
193e1051a39Sopenharmony_ci    @a = grep(defined $ln{$nid{$_}}, 0 .. $n);
194e1051a39Sopenharmony_ci}
195e1051a39Sopenharmony_ciprintf "#define NUM_LN %d\n", $#a + 1;
196e1051a39Sopenharmony_ciprintf "static const unsigned int ln_objs[NUM_LN] = {\n";
197e1051a39Sopenharmony_ciforeach (sort { $ln{$nid{$a}} cmp $ln{$nid{$b}} } @a) {
198e1051a39Sopenharmony_ci    printf "    %4d,    /* \"$ln{$nid{$_}}\" */\n", $_;
199e1051a39Sopenharmony_ci}
200e1051a39Sopenharmony_ciprint  "};\n\n";
201e1051a39Sopenharmony_ci
202e1051a39Sopenharmony_ci{
203e1051a39Sopenharmony_ci    no warnings "uninitialized";
204e1051a39Sopenharmony_ci    @a = grep(defined $obj{$nid{$_}}, 0 .. $n);
205e1051a39Sopenharmony_ci}
206e1051a39Sopenharmony_ciprintf "#define NUM_OBJ %d\n", $#a + 1;
207e1051a39Sopenharmony_ciprintf "static const unsigned int obj_objs[NUM_OBJ] = {\n";
208e1051a39Sopenharmony_ci
209e1051a39Sopenharmony_ci# Compare DER; prefer shorter; if some length, use the "smaller" encoding.
210e1051a39Sopenharmony_cisub obj_cmp
211e1051a39Sopenharmony_ci{
212e1051a39Sopenharmony_ci    no warnings "uninitialized";
213e1051a39Sopenharmony_ci    my $A = $obj_len{$obj{$nid{$a}}};
214e1051a39Sopenharmony_ci    my $B = $obj_len{$obj{$nid{$b}}};
215e1051a39Sopenharmony_ci    my $r = $A - $B;
216e1051a39Sopenharmony_ci    return $r if $r != 0;
217e1051a39Sopenharmony_ci
218e1051a39Sopenharmony_ci    $A = $obj_der{$obj{$nid{$a}}};
219e1051a39Sopenharmony_ci    $B = $obj_der{$obj{$nid{$b}}};
220e1051a39Sopenharmony_ci    return $A cmp $B;
221e1051a39Sopenharmony_ci}
222e1051a39Sopenharmony_ciforeach (sort obj_cmp @a) {
223e1051a39Sopenharmony_ci    my $m = $obj{$nid{$_}};
224e1051a39Sopenharmony_ci    my $v = $objd{$m};
225e1051a39Sopenharmony_ci    $v =~ s/L//g;
226e1051a39Sopenharmony_ci    $v =~ s/,/ /g;
227e1051a39Sopenharmony_ci    printf "    %4d,    /* %-32s %s */\n", $_, $m, $v;
228e1051a39Sopenharmony_ci}
229e1051a39Sopenharmony_ciprint  "};\n";
230