aboutsummaryrefslogtreecommitdiff
path: root/providers
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-03-31 16:42:04 +0200
committerRichard Levitte <levitte@openssl.org>2020-04-07 11:16:56 +0200
commit77de6bb38d3bc247eac548715969b01cc2b752bb (patch)
treecad6bccac30b5c94716a60c28046fc426080df1e /providers
parent3cb55fe47c3398b81956e4fe20c4004524d47519 (diff)
downloadopenssl-77de6bb38d3bc247eac548715969b01cc2b752bb.zip
openssl-77de6bb38d3bc247eac548715969b01cc2b752bb.tar.gz
openssl-77de6bb38d3bc247eac548715969b01cc2b752bb.tar.bz2
Add perl support to parse and DER encode ASN.1 OID specs
We have an old OID database that's not as readable as would be desired, and we have spots with hand coded DER for well known OIDs. The perl modules added here give enough support that we can parse OBJECT IDENTIFIER definitions and encode them as DER. OpenSSL::OID is a general OID parsing and encoding of ASN.1 definitions, and supports enough of the X.680 syntax to understand what we find in RFCs and similar documents and produce the DER encoding for them. oids_to_c is a specialized module to convert the DER encoding from OpenSSL::OID to C code. This is primarily useful in file templates that are processed with util/dofile.pl. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/11450)
Diffstat (limited to 'providers')
-rw-r--r--providers/common/der/oids_to_c.pm111
1 files changed, 111 insertions, 0 deletions
diff --git a/providers/common/der/oids_to_c.pm b/providers/common/der/oids_to_c.pm
new file mode 100644
index 0000000..64e6c07
--- /dev/null
+++ b/providers/common/der/oids_to_c.pm
@@ -0,0 +1,111 @@
+#! /usr/bin/env perl
+# Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use warnings;
+
+package oids_to_c;
+
+use Carp;
+use File::Spec;
+use OpenSSL::OID;
+
+my $OID_name_re = qr/([a-z](?:[-_A-Za-z0-9]*[A-Za-z0-9])?)/;
+my $OID_value_re = qr/(\{.*?\})/s;
+my $OID_def_re = qr/
+ ${OID_name_re} \s+ OBJECT \s+ IDENTIFIER \s*
+ ::=
+ \s* ${OID_value_re}
+ /x;
+
+use Data::Dumper;
+
+sub filter_to_H {
+ my ($name, $comment) = @{ shift() };
+ my @oid_nums = @_;
+
+ (my $C_name = $name) =~ s|-|_|g;
+ my $C_bytes_size = 2 + scalar @_;
+
+ return <<"_____";
+extern const unsigned char der_oid_${C_name}[$C_bytes_size];
+_____
+}
+
+sub filter_to_C {
+ my ($name, $comment) = @{ shift() };
+ my @oid_nums = @_;
+ my $oid_size = scalar @oid_nums;
+
+ croak "Unsupported OID size (>127 bytes)" if $oid_size > 127;
+
+ (my $C_comment = $comment) =~ s|^| * |msg;
+ $C_comment = "\n/*\n${C_comment}\n */" if $C_comment ne '';
+ (my $C_name = $name) =~ s|-|_|g;
+ my $C_bytes_size = 2 + $oid_size;
+ my $C_bytes = join(', ', map { sprintf("0x%02X", $_) } @oid_nums );
+
+ return <<"_____";
+$C_comment
+#define DER_OID_V_${C_name} DER_P_OBJECT, $oid_size, ${C_bytes}
+#define DER_OID_SZ_${C_name} ${C_bytes_size}
+const unsigned char der_oid_${C_name}[DER_OID_SZ_${C_name}] = {
+ DER_OID_V_${C_name}
+};
+_____
+}
+
+sub _process {
+ my %opts = %{ pop @_ } if ref $_[$#_] eq 'HASH';
+
+ # To maintain input order
+ my @OID_names = ();
+
+ foreach my $file (@_) {
+ my $input = File::Spec->catfile($opts{dir}, $file);
+ open my $fh, $input or die "Reading $input: $!\n";
+
+ my $text = join('',
+ map {
+ s|--.*(\R)$|$1|;
+ $_;
+ } <$fh>);
+ # print STDERR "-----BEGIN DEBUG-----\n";
+ # print STDERR $text;
+ # print STDERR "-----END DEBUG-----\n";
+ use re 'debugcolor';
+ while ($text =~ m/${OID_def_re}/sg) {
+ my $comment = $&;
+ my $name = $1;
+ my $value = $2;
+
+ # print STDERR "-----BEGIN DEBUG $name-----\n";
+ # print STDERR $value,"\n";
+ # print STDERR "-----END DEBUG $name-----\n";
+ register_oid($name, $value);
+ push @OID_names, [ $name, $comment ];
+ }
+ }
+
+ return @OID_names;
+}
+
+sub process_leaves {
+ my %opts = %{ $_[$#_] } if ref $_[$#_] eq 'HASH';
+ my @OID_names = _process @_;
+
+ my $text = '';
+ my %leaves = map { $_ => 1 } registered_oid_leaves;
+ foreach (grep { defined $leaves{$_->[0]} } @OID_names) {
+ my $lines = $opts{filter}->($_, encode_oid($_->[0]));
+ $text .= $lines;
+ }
+ return $text;
+}
+
+1;