summaryrefslogtreecommitdiff
path: root/ext/openssl/lib
diff options
context:
space:
mode:
authorHoneyryderChuck <[email protected]>2024-04-16 18:07:56 +0100
committergit <[email protected]>2024-06-27 16:00:55 +0000
commit9c5e9d29f0c9b025577cb72b421b9682bfadcd37 (patch)
tree9bfaa0a9de073d7fcc4ba3e8359a598adaf4b855 /ext/openssl/lib
parentc6a0d03649c686a537c1f513a1e32205ac6a6512 (diff)
[ruby/openssl] rewriting most of the asn1 init code in ruby
to have as much of the lib in ruby as possible https://github.com/ruby/openssl/commit/8305051728
Diffstat (limited to 'ext/openssl/lib')
-rw-r--r--ext/openssl/lib/openssl.rb1
-rw-r--r--ext/openssl/lib/openssl/asn1.rb188
2 files changed, 189 insertions, 0 deletions
diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb
index f5ca956d07..0889923890 100644
--- a/ext/openssl/lib/openssl.rb
+++ b/ext/openssl/lib/openssl.rb
@@ -13,6 +13,7 @@
require 'openssl.so'
require_relative 'openssl/bn'
+require_relative 'openssl/asn1'
require_relative 'openssl/pkey'
require_relative 'openssl/cipher'
require_relative 'openssl/digest'
diff --git a/ext/openssl/lib/openssl/asn1.rb b/ext/openssl/lib/openssl/asn1.rb
new file mode 100644
index 0000000000..89fa28e1fb
--- /dev/null
+++ b/ext/openssl/lib/openssl/asn1.rb
@@ -0,0 +1,188 @@
+# frozen_string_literal: true
+#--
+#
+# = Ruby-space definitions that completes C-space funcs for ASN.1
+#
+# = Licence
+# This program is licensed under the same licence as Ruby.
+# (See the file 'COPYING'.)
+#++
+
+module OpenSSL
+ module ASN1
+ class ASN1Data
+ #
+ # Carries the value of a ASN.1 type.
+ # Please confer Constructive and Primitive for the mappings between
+ # ASN.1 data types and Ruby classes.
+ #
+ attr_accessor :value
+
+ # An Integer representing the tag number of this ASN1Data. Never +nil+.
+ attr_accessor :tag
+
+ # A Symbol representing the tag class of this ASN1Data. Never +nil+.
+ # See ASN1Data for possible values.
+ attr_accessor :tag_class
+
+ #
+ # Never +nil+. A boolean value indicating whether the encoding uses
+ # indefinite length (in the case of parsing) or whether an indefinite
+ # length form shall be used (in the encoding case).
+ # In DER, every value uses definite length form. But in scenarios where
+ # large amounts of data need to be transferred it might be desirable to
+ # have some kind of streaming support available.
+ # For example, huge OCTET STRINGs are preferably sent in smaller-sized
+ # chunks, each at a time.
+ # This is possible in BER by setting the length bytes of an encoding
+ # to zero and by this indicating that the following value will be
+ # sent in chunks. Indefinite length encodings are always constructed.
+ # The end of such a stream of chunks is indicated by sending a EOC
+ # (End of Content) tag. SETs and SEQUENCEs may use an indefinite length
+ # encoding, but also primitive types such as e.g. OCTET STRINGS or
+ # BIT STRINGS may leverage this functionality (cf. ITU-T X.690).
+ #
+ attr_accessor :indefinite_length
+
+ alias infinite_length indefinite_length
+ alias infinite_length= indefinite_length=
+
+ #
+ # :call-seq:
+ # OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data
+ #
+ # _value_: Please have a look at Constructive and Primitive to see how Ruby
+ # types are mapped to ASN.1 types and vice versa.
+ #
+ # _tag_: An Integer indicating the tag number.
+ #
+ # _tag_class_: A Symbol indicating the tag class. Please cf. ASN1 for
+ # possible values.
+ #
+ # == Example
+ # asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42)
+ # tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER
+ #
+ def initialize(value, tag, tag_class)
+ raise ASN1Error, "invalid tag class" unless tag_class.is_a?(Symbol)
+
+ @tag = tag
+ @value = value
+ @tag_class = tag_class
+ @indefinite_length = false
+ end
+ end
+
+ module TaggedASN1Data
+ #
+ # May be used as a hint for encoding a value either implicitly or
+ # explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
+ # _tagging_ is not set when a ASN.1 structure is parsed using
+ # OpenSSL::ASN1.decode.
+ #
+ attr_accessor :tagging
+
+ # :call-seq:
+ # OpenSSL::ASN1::Primitive.new(value [, tag, tagging, tag_class ]) => Primitive
+ #
+ # _value_: is mandatory.
+ #
+ # _tag_: optional, may be specified for tagged values. If no _tag_ is
+ # specified, the UNIVERSAL tag corresponding to the Primitive sub-class
+ # is used by default.
+ #
+ # _tagging_: may be used as an encoding hint to encode a value either
+ # explicitly or implicitly, see ASN1 for possible values.
+ #
+ # _tag_class_: if _tag_ and _tagging_ are +nil+ then this is set to
+ # +:UNIVERSAL+ by default. If either _tag_ or _tagging_ are set then
+ # +:CONTEXT_SPECIFIC+ is used as the default. For possible values please
+ # cf. ASN1.
+ #
+ # == Example
+ # int = OpenSSL::ASN1::Integer.new(42)
+ # zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :IMPLICIT)
+ # private_explicit_zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :EXPLICIT, :PRIVATE)
+ #
+ def initialize(value, tag = nil, tagging = nil, tag_class = nil)
+ tag ||= ASN1.take_default_tag(self.class)
+
+ raise ASN1Error, "must specify tag number" unless tag
+
+ if tagging
+ raise ASN1Error, "invalid tagging method" unless tagging.is_a?(Symbol)
+ end
+
+ tag_class ||= tagging ? :CONTEXT_SPECIFIC : :UNIVERSAL
+
+ raise ASN1Error, "invalid tag class" unless tag_class.is_a?(Symbol)
+
+ @tagging = tagging
+ super(value ,tag, tag_class)
+ end
+ end
+
+ class Primitive < ASN1Data
+ include TaggedASN1Data
+
+ undef_method :indefinite_length=
+ undef_method :infinite_length=
+ end
+
+ class Constructive < ASN1Data
+ include TaggedASN1Data
+ include Enumerable
+
+ # :call-seq:
+ # asn1_ary.each { |asn1| block } => asn1_ary
+ #
+ # Calls the given block once for each element in self, passing that element
+ # as parameter _asn1_. If no block is given, an enumerator is returned
+ # instead.
+ #
+ # == Example
+ # asn1_ary.each do |asn1|
+ # puts asn1
+ # end
+ #
+ def each(&blk)
+ @value.each(&blk)
+
+ self
+ end
+ end
+
+ class Boolean < Primitive ; end
+ class Integer < Primitive ; end
+ class Enumerated < Primitive ; end
+
+ class BitString < Primitive
+ attr_accessor :unused_bits
+
+ def initialize(*)
+ super
+
+ @unused_bits = 0
+ end
+ end
+
+ class EndOfContent < ASN1Data
+ def initialize
+ super("", 0, :UNIVERSAL)
+ end
+ end
+
+ # :nodoc:
+ def self.take_default_tag(klass)
+ tag = CLASS_TAG_MAP[klass]
+
+ return tag if tag
+
+ sklass = klass.superclass
+
+ return unless sklass
+
+ take_default_tag(sklass)
+ end
+ end
+end