]> git.ipfire.org Git - thirdparty/openssl.git/blob - util/mkdef.pl
Remove RSA SSLv23 padding mode
[thirdparty/openssl.git] / util / mkdef.pl
1 #! /usr/bin/env perl
2 # Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the Apache License 2.0 (the "License"). You may not use
5 # this file except in compliance with the License. You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9 # Generate a linker version script suitable for the given platform
10 # from a given ordinals file.
11
12 use strict;
13 use warnings;
14
15 use Getopt::Long;
16 use FindBin;
17 use lib "$FindBin::Bin/perl";
18
19 use OpenSSL::Ordinals;
20
21 use lib '.';
22 use configdata;
23
24 use File::Spec::Functions;
25 use lib catdir($config{sourcedir}, 'Configurations');
26 use platform;
27
28 my $name = undef; # internal library/module name
29 my $ordinals_file = undef; # the ordinals file to use
30 my $version = undef; # the version to use for the library
31 my $OS = undef; # the operating system family
32 my $verbose = 0;
33 my $ctest = 0;
34 my $debug = 0;
35
36 # For VMS, some modules may have case insensitive names
37 my $case_insensitive = 0;
38
39 GetOptions('name=s' => \$name,
40 'ordinals=s' => \$ordinals_file,
41 'version=s' => \$version,
42 'OS=s' => \$OS,
43 'ctest' => \$ctest,
44 'verbose' => \$verbose,
45 # For VMS
46 'case-insensitive' => \$case_insensitive)
47 or die "Error in command line arguments\n";
48
49 die "Please supply arguments\n"
50 unless $name && $ordinals_file && $OS;
51
52 # When building a "variant" shared library, with a custom SONAME, also customize
53 # all the symbol versions. This produces a shared object that can coexist
54 # without conflict in the same address space as a default build, or an object
55 # with a different variant tag.
56 #
57 # For example, with a target definition that includes:
58 #
59 # shlib_variant => "-opt",
60 #
61 # we build the following objects:
62 #
63 # $ perl -le '
64 # for (@ARGV) {
65 # if ($l = readlink) {
66 # printf "%s -> %s\n", $_, $l
67 # } else {
68 # print
69 # }
70 # }' *.so*
71 # libcrypto-opt.so.1.1
72 # libcrypto.so -> libcrypto-opt.so.1.1
73 # libssl-opt.so.1.1
74 # libssl.so -> libssl-opt.so.1.1
75 #
76 # whose SONAMEs and dependencies are:
77 #
78 # $ for l in *.so; do
79 # echo $l
80 # readelf -d $l | egrep 'SONAME|NEEDED.*(ssl|crypto)'
81 # done
82 # libcrypto.so
83 # 0x000000000000000e (SONAME) Library soname: [libcrypto-opt.so.1.1]
84 # libssl.so
85 # 0x0000000000000001 (NEEDED) Shared library: [libcrypto-opt.so.1.1]
86 # 0x000000000000000e (SONAME) Library soname: [libssl-opt.so.1.1]
87 #
88 # We case-fold the variant tag to upper case and replace all non-alnum
89 # characters with "_". This yields the following symbol versions:
90 #
91 # $ nm libcrypto.so | grep -w A
92 # 0000000000000000 A OPENSSL_OPT_1_1_0
93 # 0000000000000000 A OPENSSL_OPT_1_1_0a
94 # 0000000000000000 A OPENSSL_OPT_1_1_0c
95 # 0000000000000000 A OPENSSL_OPT_1_1_0d
96 # 0000000000000000 A OPENSSL_OPT_1_1_0f
97 # 0000000000000000 A OPENSSL_OPT_1_1_0g
98 # $ nm libssl.so | grep -w A
99 # 0000000000000000 A OPENSSL_OPT_1_1_0
100 # 0000000000000000 A OPENSSL_OPT_1_1_0d
101 #
102 (my $SO_VARIANT = uc($target{"shlib_variant"} // '')) =~ s/\W/_/g;
103
104 my $libname = platform->sharedname($name);
105
106 my %OS_data = (
107 solaris => { writer => \&writer_linux,
108 sort => sorter_linux(),
109 platforms => { UNIX => 1 } },
110 "solaris-gcc" => 'solaris', # alias
111 linux => 'solaris', # alias
112 "bsd-gcc" => 'solaris', # alias
113 aix => { writer => \&writer_aix,
114 sort => sorter_unix(),
115 platforms => { UNIX => 1 } },
116 VMS => { writer => \&writer_VMS,
117 sort => OpenSSL::Ordinals::by_number(),
118 platforms => { VMS => 1 } },
119 vms => 'VMS', # alias
120 WINDOWS => { writer => \&writer_windows,
121 sort => OpenSSL::Ordinals::by_name(),
122 platforms => { WIN32 => 1,
123 _WIN32 => 1 } },
124 windows => 'WINDOWS', # alias
125 WIN32 => 'WINDOWS', # alias
126 win32 => 'WIN32', # alias
127 32 => 'WIN32', # alias
128 NT => 'WIN32', # alias
129 nt => 'WIN32', # alias
130 mingw => 'WINDOWS', # alias
131 nonstop => { writer => \&writer_nonstop,
132 sort => OpenSSL::Ordinals::by_name(),
133 platforms => { TANDEM => 1 } },
134 );
135
136 do {
137 die "Unknown operating system family $OS\n"
138 unless exists $OS_data{$OS};
139 $OS = $OS_data{$OS};
140 } while(ref($OS) eq '');
141
142 my %disabled_uc = map { my $x = uc $_; $x =~ s|-|_|g; $x => 1 } keys %disabled;
143
144 my %ordinal_opts = ();
145 $ordinal_opts{sort} = $OS->{sort} if $OS->{sort};
146 $ordinal_opts{filter} =
147 sub {
148 my $item = shift;
149 return
150 $item->exists()
151 && platform_filter($item)
152 && feature_filter($item);
153 };
154 my $ordinals = OpenSSL::Ordinals->new(from => $ordinals_file);
155
156 my $writer = $OS->{writer};
157 $writer = \&writer_ctest if $ctest;
158
159 $writer->($ordinals->items(%ordinal_opts));
160
161 exit 0;
162
163 sub platform_filter {
164 my $item = shift;
165 my %platforms = ( $item->platforms() );
166
167 # True if no platforms are defined
168 return 1 if scalar keys %platforms == 0;
169
170 # For any item platform tag, return the equivalence with the
171 # current platform settings if it exists there, return 0 otherwise
172 # if the item platform tag is true
173 for (keys %platforms) {
174 if (exists $OS->{platforms}->{$_}) {
175 return $platforms{$_} == $OS->{platforms}->{$_};
176 }
177 if ($platforms{$_}) {
178 return 0;
179 }
180 }
181
182 # Found no match? Then it's a go
183 return 1;
184 }
185
186 sub feature_filter {
187 my $item = shift;
188 my @features = ( $item->features() );
189
190 # True if no features are defined
191 return 1 if scalar @features == 0;
192
193 my $verdict = ! grep { $disabled_uc{$_} } @features;
194
195 if ($disabled{deprecated}) {
196 foreach (@features) {
197 next unless /^DEPRECATEDIN_(\d+)_(\d+)(?:_(\d+))?$/;
198 my $symdep = $1 * 10000 + $2 * 100 + ($3 // 0);
199 $verdict = 0 if $config{api} >= $symdep;
200 print STDERR "DEBUG: \$symdep = $symdep, \$verdict = $verdict\n"
201 if $debug && $1 == 0;
202 }
203 }
204
205 return $verdict;
206 }
207
208 sub sorter_unix {
209 my $by_name = OpenSSL::Ordinals::by_name();
210 my %weight = (
211 'FUNCTION' => 1,
212 'VARIABLE' => 2
213 );
214
215 return sub {
216 my $item1 = shift;
217 my $item2 = shift;
218
219 my $verdict = $weight{$item1->type()} <=> $weight{$item2->type()};
220 if ($verdict == 0) {
221 $verdict = $by_name->($item1, $item2);
222 }
223 return $verdict;
224 };
225 }
226
227 sub sorter_linux {
228 my $by_version = OpenSSL::Ordinals::by_version();
229 my $by_unix = sorter_unix();
230
231 return sub {
232 my $item1 = shift;
233 my $item2 = shift;
234
235 my $verdict = $by_version->($item1, $item2);
236 if ($verdict == 0) {
237 $verdict = $by_unix->($item1, $item2);
238 }
239 return $verdict;
240 };
241 }
242
243 sub writer_linux {
244 my $thisversion = '';
245 my $currversion_s = '';
246 my $prevversion_s = '';
247 my $indent = 0;
248
249 for (@_) {
250 if ($thisversion && $_->version() ne $thisversion) {
251 die "$ordinals_file: It doesn't make sense to have both versioned ",
252 "and unversioned symbols"
253 if $thisversion eq '*';
254 print <<"_____";
255 }${prevversion_s};
256 _____
257 $prevversion_s = " OPENSSL${SO_VARIANT}_$thisversion";
258 $thisversion = ''; # Trigger start of next section
259 }
260 unless ($thisversion) {
261 $indent = 0;
262 $thisversion = $_->version();
263 $currversion_s = '';
264 $currversion_s = "OPENSSL${SO_VARIANT}_$thisversion "
265 if $thisversion ne '*';
266 print <<"_____";
267 ${currversion_s}{
268 global:
269 _____
270 }
271 print ' ', $_->name(), ";\n";
272 }
273
274 print <<"_____";
275 local: *;
276 }${prevversion_s};
277 _____
278 }
279
280 sub writer_aix {
281 for (@_) {
282 print $_->name(),"\n";
283 }
284 }
285
286 sub writer_nonstop {
287 for (@_) {
288 print "-export ",$_->name(),"\n";
289 }
290 }
291
292 sub writer_windows {
293 print <<"_____";
294 ;
295 ; Definition file for the DLL version of the $libname library from OpenSSL
296 ;
297
298 LIBRARY $libname
299
300 EXPORTS
301 _____
302 for (@_) {
303 print " ",$_->name(),"\n";
304 }
305 }
306
307 sub collect_VMS_mixedcase {
308 return [ 'SPARE', 'SPARE' ] unless @_;
309
310 my $s = shift;
311 my $s_uc = uc($s);
312 my $type = shift;
313
314 return [ "$s=$type", 'SPARE' ] if $s_uc eq $s;
315 return [ "$s_uc/$s=$type", "$s=$type" ];
316 }
317
318 sub collect_VMS_uppercase {
319 return [ 'SPARE' ] unless @_;
320
321 my $s = shift;
322 my $s_uc = uc($s);
323 my $type = shift;
324
325 return [ "$s_uc=$type" ];
326 }
327
328 sub writer_VMS {
329 my @slot_collection = ();
330 my $collector =
331 $case_insensitive ? \&collect_VMS_uppercase : \&collect_VMS_mixedcase;
332
333 my $last_num = 0;
334 foreach (@_) {
335 my $this_num = $_->number();
336 $this_num = $last_num + 1 if $this_num =~ m|^\?|;
337
338 while (++$last_num < $this_num) {
339 push @slot_collection, $collector->(); # Just occupy a slot
340 }
341 my $type = {
342 FUNCTION => 'PROCEDURE',
343 VARIABLE => 'DATA'
344 } -> {$_->type()};
345 push @slot_collection, $collector->($_->name(), $type);
346 }
347
348 print <<"_____" if defined $version;
349 IDENTIFICATION=$version
350 _____
351 print <<"_____" unless $case_insensitive;
352 CASE_SENSITIVE=YES
353 _____
354 print <<"_____";
355 SYMBOL_VECTOR=(-
356 _____
357 # It's uncertain how long aggregated lines the linker can handle,
358 # but it has been observed that at least 1024 characters is ok.
359 # Either way, this means that we need to keep track of the total
360 # line length of each "SYMBOL_VECTOR" statement. Fortunately, we
361 # can have more than one of those...
362 my $symvtextcount = 16; # The length of "SYMBOL_VECTOR=("
363 while (@slot_collection) {
364 my $set = shift @slot_collection;
365 my $settextlength = 0;
366 foreach (@$set) {
367 $settextlength +=
368 + 3 # two space indentation and comma
369 + length($_)
370 + 1 # postdent
371 ;
372 }
373 $settextlength--; # only one space indentation on the first one
374 my $firstcomma = ',';
375
376 if ($symvtextcount + $settextlength > 1024) {
377 print <<"_____";
378 )
379 SYMBOL_VECTOR=(-
380 _____
381 $symvtextcount = 16; # The length of "SYMBOL_VECTOR=("
382 }
383 if ($symvtextcount == 16) {
384 $firstcomma = '';
385 }
386
387 my $indent = ' '.$firstcomma;
388 foreach (@$set) {
389 print <<"_____";
390 $indent$_ -
391 _____
392 $symvtextcount += length($indent) + length($_) + 1;
393 $indent = ' ,';
394 }
395 }
396 print <<"_____";
397 )
398 _____
399
400 if (defined $version) {
401 $version =~ /^(\d+)\.(\d+)\.(\d+)/;
402 my $libvmajor = $1;
403 my $libvminor = $2 * 100 + $3;
404 print <<"_____";
405 GSMATCH=LEQUAL,$libvmajor,$libvminor
406 _____
407 }
408 }
409
410 sub writer_ctest {
411 print <<'_____';
412 /*
413 * Test file to check all DEF file symbols are present by trying
414 * to link to all of them. This is *not* intended to be run!
415 */
416
417 int main()
418 {
419 _____
420
421 my $last_num = 0;
422 for (@_) {
423 my $this_num = $_->number();
424 $this_num = $last_num + 1 if $this_num =~ m|^\?|;
425
426 if ($_->type() eq 'VARIABLE') {
427 print "\textern int ", $_->name(), '; /* type unknown */ /* ',
428 $this_num, ' ', $_->version(), " */\n";
429 } else {
430 print "\textern int ", $_->name(), '(); /* type unknown */ /* ',
431 $this_num, ' ', $_->version(), " */\n";
432 }
433
434 $last_num = $this_num;
435 }
436 print <<'_____';
437 }
438 _____
439 }