diff options
author | rhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-09-03 12:35:27 +0000 |
---|---|---|
committer | rhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-09-03 12:35:27 +0000 |
commit | 609103dbb5fb182eec12f052226c43e39b907682 (patch) | |
tree | 881cdacc3312e65261ebd34a807c75ee09fdb303 /ext/openssl/ossl_asn1.c | |
parent | b9801bb8b2f5ce91755e0076d79140a72ff94d6a (diff) |
openssl: import v2.1.0.beta1
Import Ruby/OpenSSL 2.1.0.beta1. The full commit log since v2.0.5
(imported by r59567) can be found at:
https://github.com/ruby/openssl/compare/v2.0.5...v2.1.0.beta1
----------------------------------------------------------------
Antonio Terceiro (1):
test/test_ssl: explicitly accept TLS 1.1 in corresponding test
Colby Swandale (1):
document using secure protocol to fetch git master in Bundler
Colton Jenkins (1):
Add fips_mode_get to return fips_mode
Kazuki Yamaguchi (85):
Start preparing for 2.1.0
Remove support for OpenSSL 0.9.8 and 1.0.0
bn: refine tests
bn: implement unary {plus,minus} operators for OpenSSL::BN
bn: implement OpenSSL::BN#negative?
Don't define main() when built with --enable-debug
test: let OpenSSL::TestCase include OpenSSL::TestUtils
test: prepare test PKey instances on demand
Add OpenSSL.print_mem_leaks
Enable OSSL_MDEBUG on CI builds
ssl: move default DH parameters from OpenSSL::PKey::DH
Make exceptions with the same format regardless of OpenSSL.debug
ssl: show reason of 'certificate verify error' in exception message
ssl: remove OpenSSL::ExtConfig::TLS_DH_anon_WITH_AES_256_GCM_SHA384
ssl: do not confuse different ex_data index registries
ssl: assume SSL/SSL_CTX always have a valid reference to the Ruby object
Fix RDoc markup
ssl: suppress compiler warning
ext/openssl/deprecation.rb: remove broken-apple-openssl
extconf.rb: print informative message if OpenSSL can't be found
Rakefile: compile the extension before test
kdf: introduce OpenSSL::KDF module
ossl.h: add NUM2UINT64T() macro
kdf: add scrypt
Expand rb_define_copy_func() macro
Expand FPTR_TO_FD() macro
Remove SafeGet*() macros
cipher: rename GetCipherPtr() to ossl_evp_get_cipherbyname()
digest: rename GetDigestPtr() to ossl_evp_get_digestbyname()
Add ossl_str_new(), an exception-safe rb_str_new()
bio: simplify ossl_membio2str() using ossl_str_new()
Remove unused functions and macros
Drop support for LibreSSL 2.3
ocsp: add OpenSSL::OCSP::Request#signed?
asn1: infinite length -> indefinite length
asn1: rearrange tests
ssl: remove a needless NULL check in SSL::SSLContext#ciphers
ssl: return nil in SSL::SSLSocket#cipher if session is not started
asn1: remove an unnecessary function prototype
asn1: require tag information when instantiating generic type
asn1: initialize 'unused_bits' attribute of BitString with 0
asn1: check for illegal 'unused_bits' value of BitString
asn1: disallow NULL to be passed to asn1time_to_time()
asn1: avoid truncating OID in OpenSSL::ASN1::ObjectId#oid
asn1: allow constructed encoding with definite length form
asn1: prohibit indefinite length form for primitive encoding
asn1: allow tag number to be >= 32 for universal tag class
asn1: use ossl_asn1_tag()
asn1: clean up OpenSSL::ASN1::Constructive#to_der
asn1: harmonize OpenSSL::ASN1::*#to_der
asn1: prevent EOC octets from being in the middle of the content
asn1: do not treat EOC octets as part of content octets
x509name: add 'loc' and 'set' kwargs to OpenSSL::X509::Name#add_entry
ssl: do not call session_remove_cb during GC
Backport "Merge branch 'topic/test-memory-leak'" to maint
cipher: update the documentation for Cipher#auth_tag=
Rakefile: let sync:to_ruby know about test/openssl/fixtures
test: fix formatting
test/utils: remove OpenSSL::TestUtils.silent
test/utils: add SSLTestCase#tls12_supported?
test/utils: have start_server yield only the port number
test/utils: do not set ecdh_curves in start_server
test/utils: let server_loop close socket
test/utils: improve error handling in start_server
test/utils: add OpenSSL::TestUtils.openssl? and .libressl?
test/utils: do not use DSA certificates in SSL tests
test/test_ssl: remove test_invalid_shutdown_by_gc
test/test_ssl: move test_multibyte_read_write to test_pair
test/test_ssl_session: rearrange tests
test/test_pair, test/test_ssl: fix for TLS 1.3
ssl: remove useless call to rb_thread_wait_fd()
ssl: fix NPN support
ssl: mark OpenSSL::SSL::SSLContext::DEFAULT_{1024,2048} as private
ssl: use 2048-bit group in the default tmp_dh_cb
ssl: ensure that SSL option flags are non-negative
ssl: update OpenSSL::SSL::OP_* flags
ssl: prefer TLS_method() over SSLv23_method()
ssl: add SSLContext#min_version= and #max_version=
ssl: rework SSLContext#ssl_version=
test/test_x509name: change script encoding to ASCII-8BIT
x509name: refactor OpenSSL::X509::Name#to_s
x509name: add OpenSSL::X509::Name#to_utf8
x509name: add OpenSSL::X509::Name#inspect
x509name: update regexp in OpenSSL::X509::Name.parse
Ruby/OpenSSL 2.1.0.beta1
Marcus Stollsteimer (1):
Fix rdoc for core Integer class
nobu (4):
[DOC] {read,write}_nonblock with exception: false
[DOC] keyword argument _exception_
[DOC] mark up literals
Revert r57690 except for read_nonblock
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59734 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/openssl/ossl_asn1.c')
-rw-r--r-- | ext/openssl/ossl_asn1.c | 660 |
1 files changed, 287 insertions, 373 deletions
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index 1d3ee4ac18..efa6b78742 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -9,11 +9,9 @@ */ #include "ossl.h" -static VALUE join_der(VALUE enumerable); static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth, int yield, long *num_read); static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self); -static VALUE ossl_asn1eoc_initialize(VALUE self); /* * DATE conversion @@ -25,7 +23,6 @@ asn1time_to_time(const ASN1_TIME *time) VALUE argv[6]; int count; - if (!time || !time->data) return Qnil; memset(&tm, 0, sizeof(struct tm)); switch (time->type) { @@ -72,7 +69,6 @@ asn1time_to_time(const ASN1_TIME *time) return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv); } -#if defined(HAVE_ASN1_TIME_ADJ) void ossl_time_split(VALUE time, time_t *sec, int *days) { @@ -88,13 +84,6 @@ ossl_time_split(VALUE time, time_t *sec, int *days) *sec = NUM2TIMET(rb_funcall(num, rb_intern("%"), 1, INT2FIX(86400))); } } -#else -time_t -time_to_time_t(VALUE time) -{ - return (time_t)NUM2TIMET(rb_Integer(time)); -} -#endif /* * STRING conversion @@ -155,13 +144,13 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai) #define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG) #define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING) #define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS) -#define ossl_asn1_get_infinite_length(o) rb_attr_get((o),sivINFINITE_LENGTH) +#define ossl_asn1_get_indefinite_length(o) rb_attr_get((o),sivINDEFINITE_LENGTH) #define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v)) #define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v)) #define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v)) #define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v)) -#define ossl_asn1_set_infinite_length(o,v) rb_ivar_set((o),sivINFINITE_LENGTH,(v)) +#define ossl_asn1_set_indefinite_length(o,v) rb_ivar_set((o),sivINDEFINITE_LENGTH,(v)) VALUE mASN1; VALUE eASN1Error; @@ -187,7 +176,7 @@ VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ static VALUE sym_IMPLICIT, sym_EXPLICIT; static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE; -static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINFINITE_LENGTH, sivUNUSED_BITS; +static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINDEFINITE_LENGTH, sivUNUSED_BITS; static ID id_each; /* @@ -213,13 +202,15 @@ obj_to_asn1bstr(VALUE obj, long unused_bits) { ASN1_BIT_STRING *bstr; - if(unused_bits < 0) unused_bits = 0; + if (unused_bits < 0 || unused_bits > 7) + ossl_raise(eASN1Error, "unused_bits for a bitstring value must be in "\ + "the range 0 to 7"); StringValue(obj); if(!(bstr = ASN1_BIT_STRING_new())) ossl_raise(eASN1Error, NULL); ASN1_BIT_STRING_set(bstr, (unsigned char *)RSTRING_PTR(obj), RSTRING_LENINT(obj)); bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */ - bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07); + bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT | unused_bits; return bstr; } @@ -269,15 +260,10 @@ obj_to_asn1utime(VALUE time) time_t sec; ASN1_UTCTIME *t; -#if defined(HAVE_ASN1_TIME_ADJ) int off_days; ossl_time_split(time, &sec, &off_days); if (!(t = ASN1_UTCTIME_adj(NULL, sec, off_days, 0))) -#else - sec = time_to_time_t(time); - if (!(t = ASN1_UTCTIME_set(NULL, sec))) -#endif ossl_raise(eASN1Error, NULL); return t; @@ -289,15 +275,10 @@ obj_to_asn1gtime(VALUE time) time_t sec; ASN1_GENERALIZEDTIME *t; -#if defined(HAVE_ASN1_TIME_ADJ) int off_days; ossl_time_split(time, &sec, &off_days); if (!(t = ASN1_GENERALIZEDTIME_adj(NULL, sec, off_days, 0))) -#else - sec = time_to_time_t(time); - if (!(t = ASN1_GENERALIZEDTIME_set(NULL, sec))) -#endif ossl_raise(eASN1Error, NULL); return t; @@ -517,7 +498,7 @@ ossl_asn1_get_asn1type(VALUE obj) VALUE value, rflag; void *ptr; void (*free_func)(); - int tag, flag; + int tag; tag = ossl_asn1_default_tag(obj); value = ossl_asn1_get_value(obj); @@ -533,8 +514,7 @@ ossl_asn1_get_asn1type(VALUE obj) break; case V_ASN1_BIT_STRING: rflag = rb_attr_get(obj, sivUNUSED_BITS); - flag = NIL_P(rflag) ? -1 : NUM2INT(rflag); - ptr = obj_to_asn1bstr(value, flag); + ptr = obj_to_asn1bstr(value, NUM2INT(rflag)); free_func = ASN1_BIT_STRING_free; break; case V_ASN1_NULL: @@ -598,8 +578,8 @@ ossl_asn1_default_tag(VALUE obj) return NUM2INT(tag); tmp_class = rb_class_superclass(tmp_class); } - ossl_raise(eASN1Error, "universal tag for %"PRIsVALUE" not found", - rb_obj_class(obj)); + + return -1; } static int @@ -615,20 +595,6 @@ ossl_asn1_tag(VALUE obj) } static int -ossl_asn1_is_explicit(VALUE obj) -{ - VALUE s; - - s = ossl_asn1_get_tagging(obj); - if (NIL_P(s) || s == sym_IMPLICIT) - return 0; - else if (s == sym_EXPLICIT) - return 1; - else - ossl_raise(eASN1Error, "invalid tag default"); -} - -static int ossl_asn1_tag_class(VALUE obj) { VALUE s; @@ -663,12 +629,12 @@ ossl_asn1_class2sym(int tc) * call-seq: * OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data * - * +value+: Please have a look at Constructive and Primitive to see how Ruby + * _value_: Please have a look at Constructive and Primitive to see how Ruby * types are mapped to ASN.1 types and vice versa. * - * +tag+: A +Number+ indicating the tag number. + * _tag_: An Integer indicating the tag number. * - * +tag_class+: A +Symbol+ indicating the tag class. Please cf. ASN1 for + * _tag_class_: A Symbol indicating the tag class. Please cf. ASN1 for * possible values. * * == Example @@ -680,73 +646,85 @@ ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class) { if(!SYMBOL_P(tag_class)) ossl_raise(eASN1Error, "invalid tag class"); - if (tag_class == sym_UNIVERSAL && NUM2INT(tag) > 31) - ossl_raise(eASN1Error, "tag number for Universal too large"); ossl_asn1_set_tag(self, tag); ossl_asn1_set_value(self, value); ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_infinite_length(self, Qfalse); + ossl_asn1_set_indefinite_length(self, Qfalse); return self; } static VALUE -join_der_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, str)) +to_der_internal(VALUE self, int constructed, int indef_len, VALUE body) { - i = ossl_to_der_if_possible(i); - StringValue(i); - rb_str_append(str, i); - return Qnil; -} + int encoding = constructed ? indef_len ? 2 : 1 : 0; + int tag_class = ossl_asn1_tag_class(self); + int tag_number = ossl_asn1_tag(self); + int default_tag_number = ossl_asn1_default_tag(self); + int body_length, total_length; + VALUE str; + unsigned char *p; -static VALUE -join_der(VALUE enumerable) -{ - VALUE str = rb_str_new(0, 0); - rb_block_call(enumerable, id_each, 0, 0, join_der_i, str); + body_length = RSTRING_LENINT(body); + if (ossl_asn1_get_tagging(self) == sym_EXPLICIT) { + int inner_length, e_encoding = indef_len ? 2 : 1; + + if (default_tag_number == -1) + ossl_raise(eASN1Error, "explicit tagging of unknown tag"); + + inner_length = ASN1_object_size(encoding, body_length, default_tag_number); + total_length = ASN1_object_size(e_encoding, inner_length, tag_number); + str = rb_str_new(NULL, total_length); + p = (unsigned char *)RSTRING_PTR(str); + /* Put explicit tag */ + ASN1_put_object(&p, e_encoding, inner_length, tag_number, tag_class); + /* Append inner object */ + ASN1_put_object(&p, encoding, body_length, default_tag_number, V_ASN1_UNIVERSAL); + memcpy(p, RSTRING_PTR(body), body_length); + p += body_length; + if (indef_len) { + ASN1_put_eoc(&p); /* For inner object */ + ASN1_put_eoc(&p); /* For wrapper object */ + } + } + else { + total_length = ASN1_object_size(encoding, body_length, tag_number); + str = rb_str_new(NULL, total_length); + p = (unsigned char *)RSTRING_PTR(str); + ASN1_put_object(&p, encoding, body_length, tag_number, tag_class); + memcpy(p, RSTRING_PTR(body), body_length); + p += body_length; + if (indef_len) + ASN1_put_eoc(&p); + } + assert(p - (unsigned char *)RSTRING_PTR(str) == total_length); return str; } +static VALUE ossl_asn1prim_to_der(VALUE); +static VALUE ossl_asn1cons_to_der(VALUE); /* * call-seq: * asn1.to_der => DER-encoded String * * Encodes this ASN1Data into a DER-encoded String value. The result is - * DER-encoded except for the possibility of infinite length encodings. - * Infinite length encodings are not allowed in strict DER, so strictly - * speaking the result of such an encoding would be a BER-encoding. + * DER-encoded except for the possibility of indefinite length forms. + * Indefinite length forms are not allowed in strict DER, so strictly speaking + * the result of such an encoding would be a BER-encoding. */ static VALUE ossl_asn1data_to_der(VALUE self) { - VALUE value, der, inf_length; - int tag, tag_class, is_cons = 0; - long length; - unsigned char *p; - - value = ossl_asn1_get_value(self); - if(rb_obj_is_kind_of(value, rb_cArray)){ - is_cons = 1; - value = join_der(value); - } - StringValue(value); + VALUE value = ossl_asn1_get_value(self); - tag = ossl_asn1_tag(self); - tag_class = ossl_asn1_tag_class(self); - inf_length = ossl_asn1_get_infinite_length(self); - if (inf_length == Qtrue) { - is_cons = 2; + if (rb_obj_is_kind_of(value, rb_cArray)) + return ossl_asn1cons_to_der(self); + else { + if (RTEST(ossl_asn1_get_indefinite_length(self))) + ossl_raise(eASN1Error, "indefinite length form cannot be used " \ + "with primitive encoding"); + return ossl_asn1prim_to_der(self); } - if((length = ASN1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0) - ossl_raise(eASN1Error, NULL); - der = rb_str_new(0, length); - p = (unsigned char *)RSTRING_PTR(der); - ASN1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class); - memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value)); - p += RSTRING_LEN(value); - ossl_str_adjust(der, p); - - return der; } static VALUE @@ -829,46 +807,33 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length, int tag, VALUE tc, long *num_read) { VALUE value, asn1data, ary; - int infinite; + int indefinite; long available_len, off = *offset; - infinite = (j == 0x21); + indefinite = (j == 0x21); ary = rb_ary_new(); - available_len = infinite ? max_len : length; + available_len = indefinite ? max_len : length; while (available_len > 0) { long inner_read = 0; value = ossl_asn1_decode0(pp, available_len, &off, depth + 1, yield, &inner_read); *num_read += inner_read; available_len -= inner_read; - rb_ary_push(ary, value); - if (infinite && - NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC && + if (indefinite && + ossl_asn1_tag(value) == V_ASN1_EOC && ossl_asn1_get_tag_class(value) == sym_UNIVERSAL) { break; } + rb_ary_push(ary, value); } if (tc == sym_UNIVERSAL) { VALUE args[4]; - int not_sequence_or_set; - - not_sequence_or_set = tag != V_ASN1_SEQUENCE && tag != V_ASN1_SET; - - if (not_sequence_or_set) { - if (infinite) { - asn1data = rb_obj_alloc(cASN1Constructive); - } - else { - ossl_raise(eASN1Error, "invalid non-infinite tag"); - return Qnil; - } - } - else { - VALUE klass = *ossl_asn1_info[tag].klass; - asn1data = rb_obj_alloc(klass); - } + if (tag == V_ASN1_SEQUENCE || tag == V_ASN1_SET) + asn1data = rb_obj_alloc(*ossl_asn1_info[tag].klass); + else + asn1data = rb_obj_alloc(cASN1Constructive); args[0] = ary; args[1] = INT2NUM(tag); args[2] = Qnil; @@ -880,10 +845,10 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length, ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), tc); } - if (infinite) - ossl_asn1_set_infinite_length(asn1data, Qtrue); + if (indefinite) + ossl_asn1_set_indefinite_length(asn1data, Qtrue); else - ossl_asn1_set_infinite_length(asn1data, Qfalse); + ossl_asn1_set_indefinite_length(asn1data, Qfalse); *offset = off; return asn1data; @@ -936,7 +901,8 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth, inner_read += hlen; } else { - if ((j & 0x01) && (len == 0)) ossl_raise(eASN1Error, "Infinite length for primitive value"); + if ((j & 0x01) && (len == 0)) + ossl_raise(eASN1Error, "indefinite length for primitive value"); asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read); off += hlen + len; } @@ -968,13 +934,13 @@ int_ossl_decode_sanity_check(long len, long read, long offset) * * If a block is given, it prints out each of the elements encountered. * Block parameters are (in that order): - * * depth: The recursion depth, plus one with each constructed value being encountered (Number) - * * offset: Current byte offset (Number) - * * header length: Combined length in bytes of the Tag and Length headers. (Number) - * * length: The overall remaining length of the entire data (Number) + * * depth: The recursion depth, plus one with each constructed value being encountered (Integer) + * * offset: Current byte offset (Integer) + * * header length: Combined length in bytes of the Tag and Length headers. (Integer) + * * length: The overall remaining length of the entire data (Integer) * * constructed: Whether this value is constructed or not (Boolean) * * tag_class: Current tag class (Symbol) - * * tag: The current tag (Number) + * * tag: The current tag number (Integer) * * == Example * der = File.binread('asn1data.der') @@ -1004,9 +970,9 @@ ossl_asn1_traverse(VALUE self, VALUE obj) * call-seq: * OpenSSL::ASN1.decode(der) -> ASN1Data * - * Decodes a BER- or DER-encoded value and creates an ASN1Data instance. +der+ - * may be a +String+ or any object that features a +#to_der+ method transforming - * it into a BER-/DER-encoded +String+. + * Decodes a BER- or DER-encoded value and creates an ASN1Data instance. _der_ + * may be a String or any object that features a +.to_der+ method transforming + * it into a BER-/DER-encoded String+ * * == Example * der = File.binread('asn1data') @@ -1034,9 +1000,9 @@ ossl_asn1_decode(VALUE self, VALUE obj) * call-seq: * OpenSSL::ASN1.decode_all(der) -> Array of ASN1Data * - * Similar to +decode+ with the difference that +decode+ expects one - * distinct value represented in +der+. +decode_all+ on the contrary - * decodes a sequence of sequential BER/DER values lined up in +der+ + * Similar to #decode with the difference that #decode expects one + * distinct value represented in _der_. #decode_all on the contrary + * decodes a sequence of sequential BER/DER values lined up in _der_ * and returns them as an array. * * == Example @@ -1071,19 +1037,19 @@ ossl_asn1_decode_all(VALUE self, VALUE obj) /* * call-seq: - * OpenSSL::ASN1::Primitive.new( value [, tag, tagging, tag_class ]) => Primitive + * OpenSSL::ASN1::Primitive.new(value [, tag, tagging, tag_class ]) => Primitive * - * +value+: is mandatory. + * _value_: is mandatory. * - * +tag+: optional, may be specified for tagged values. If no +tag+ is + * _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 + * _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 + * _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. * @@ -1096,9 +1062,12 @@ static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) { VALUE value, tag, tagging, tag_class; + int default_tag; rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class); - if(argc > 1){ + default_tag = ossl_asn1_default_tag(self); + + if (default_tag == -1 || argc > 1) { if(NIL_P(tag)) ossl_raise(eASN1Error, "must specify tag number"); if(!NIL_P(tagging) && !SYMBOL_P(tagging)) @@ -1111,11 +1080,9 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) } if(!SYMBOL_P(tag_class)) ossl_raise(eASN1Error, "invalid tag class"); - if (tagging == sym_IMPLICIT && NUM2INT(tag) > 31) - ossl_raise(eASN1Error, "tag number for Universal too large"); } else{ - tag = INT2NUM(ossl_asn1_default_tag(self)); + tag = INT2NUM(default_tag); tagging = Qnil; tag_class = sym_UNIVERSAL; } @@ -1123,7 +1090,9 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) ossl_asn1_set_value(self, value); ossl_asn1_set_tagging(self, tagging); ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_infinite_length(self, Qfalse); + ossl_asn1_set_indefinite_length(self, Qfalse); + if (default_tag == V_ASN1_BIT_STRING) + rb_ivar_set(self, sivUNUSED_BITS, INT2FIX(0)); return self; } @@ -1131,7 +1100,7 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) static VALUE ossl_asn1eoc_initialize(VALUE self) { VALUE tag, tagging, tag_class, value; - tag = INT2NUM(ossl_asn1_default_tag(self)); + tag = INT2FIX(0); tagging = Qnil; tag_class = sym_UNIVERSAL; value = rb_str_new("", 0); @@ -1139,51 +1108,58 @@ ossl_asn1eoc_initialize(VALUE self) { ossl_asn1_set_value(self, value); ossl_asn1_set_tagging(self, tagging); ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_infinite_length(self, Qfalse); + ossl_asn1_set_indefinite_length(self, Qfalse); return self; } +static VALUE +ossl_asn1eoc_to_der(VALUE self) +{ + return rb_str_new("\0\0", 2); +} + /* * call-seq: * asn1.to_der => DER-encoded String * - * See ASN1Data#to_der for details. * + * See ASN1Data#to_der for details. */ static VALUE ossl_asn1prim_to_der(VALUE self) { ASN1_TYPE *asn1; - int tn, tc, explicit; - long len, reallen; - unsigned char *buf, *p; + long alllen, bodylen; + unsigned char *p0, *p1; + int j, tag, tc, state; VALUE str; - tn = NUM2INT(ossl_asn1_get_tag(self)); - tc = ossl_asn1_tag_class(self); - explicit = ossl_asn1_is_explicit(self); - asn1 = ossl_asn1_get_asn1type(self); + if (ossl_asn1_default_tag(self) == -1) { + str = ossl_asn1_get_value(self); + return to_der_internal(self, 0, 0, StringValue(str)); + } - len = ASN1_object_size(1, i2d_ASN1_TYPE(asn1, NULL), tn); - if(!(buf = OPENSSL_malloc(len))){ + asn1 = ossl_asn1_get_asn1type(self); + alllen = i2d_ASN1_TYPE(asn1, NULL); + if (alllen < 0) { ASN1_TYPE_free(asn1); - ossl_raise(eASN1Error, "cannot alloc buffer"); + ossl_raise(eASN1Error, "i2d_ASN1_TYPE"); } - p = buf; - if (tc == V_ASN1_UNIVERSAL) { - i2d_ASN1_TYPE(asn1, &p); - } else if (explicit) { - ASN1_put_object(&p, 1, i2d_ASN1_TYPE(asn1, NULL), tn, tc); - i2d_ASN1_TYPE(asn1, &p); - } else { - i2d_ASN1_TYPE(asn1, &p); - *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED); + str = ossl_str_new(NULL, alllen, &state); + if (state) { + ASN1_TYPE_free(asn1); + rb_jump_tag(state); } + p0 = p1 = (unsigned char *)RSTRING_PTR(str); + i2d_ASN1_TYPE(asn1, &p0); ASN1_TYPE_free(asn1); - reallen = p - buf; - assert(reallen <= len); - str = ossl_buf2str((char *)buf, rb_long2int(reallen)); /* buf will be free in ossl_buf2str */ + assert(p0 - p1 == alllen); - return str; + /* Strip header since to_der_internal() wants only the payload */ + j = ASN1_get_object((const unsigned char **)&p1, &bodylen, &tag, &tc, alllen); + if (j & 0x80) + ossl_raise(eASN1Error, "ASN1_get_object"); /* should not happen */ + + return to_der_internal(self, 0, 0, rb_str_drop_bytes(str, alllen - bodylen)); } /* @@ -1195,92 +1171,41 @@ ossl_asn1prim_to_der(VALUE self) static VALUE ossl_asn1cons_to_der(VALUE self) { - int tag, tn, tc, explicit, constructed = 1; - int found_prim = 0, seq_len; - long length; - unsigned char *p; - VALUE value, str, inf_length; - - tn = NUM2INT(ossl_asn1_get_tag(self)); - tc = ossl_asn1_tag_class(self); - inf_length = ossl_asn1_get_infinite_length(self); - if (inf_length == Qtrue) { - VALUE ary, example; - constructed = 2; - if (rb_obj_class(self) == cASN1Sequence || - rb_obj_class(self) == cASN1Set) { - tag = ossl_asn1_default_tag(self); - } - else { /* must be a constructive encoding of a primitive value */ - ary = ossl_asn1_get_value(self); - if (!rb_obj_is_kind_of(ary, rb_cArray)) - ossl_raise(eASN1Error, "Constructive value must be an Array"); - /* Recursively descend until a primitive value is found. - The overall value of the entire constructed encoding - is of the type of the first primitive encoding to be - found. */ - while (!found_prim){ - example = rb_ary_entry(ary, 0); - if (rb_obj_is_kind_of(example, cASN1Primitive)){ - found_prim = 1; - } - else { - /* example is another ASN1Constructive */ - if (!rb_obj_is_kind_of(example, cASN1Constructive)){ - ossl_raise(eASN1Error, "invalid constructed encoding"); - return Qnil; /* dummy */ - } - ary = ossl_asn1_get_value(example); - } - } - tag = ossl_asn1_default_tag(example); - } - } - else { - if (rb_obj_class(self) == cASN1Constructive) - ossl_raise(eASN1Error, "Constructive shall only be used with infinite length"); - tag = ossl_asn1_default_tag(self); - } - explicit = ossl_asn1_is_explicit(self); - value = join_der(ossl_asn1_get_value(self)); - - seq_len = ASN1_object_size(constructed, RSTRING_LENINT(value), tag); - length = ASN1_object_size(constructed, seq_len, tn); - str = rb_str_new(0, length); - p = (unsigned char *)RSTRING_PTR(str); - if(tc == V_ASN1_UNIVERSAL) - ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc); - else{ - if(explicit){ - ASN1_put_object(&p, constructed, seq_len, tn, tc); - ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL); - } - else{ - ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc); + VALUE ary, str; + long i; + int indef_len; + + indef_len = RTEST(ossl_asn1_get_indefinite_length(self)); + ary = rb_convert_type(ossl_asn1_get_value(self), T_ARRAY, "Array", "to_a"); + str = rb_str_new(NULL, 0); + for (i = 0; i < RARRAY_LEN(ary); i++) { + VALUE item = RARRAY_AREF(ary, i); + + if (indef_len && rb_obj_is_kind_of(item, cASN1EndOfContent)) { + if (i != RARRAY_LEN(ary) - 1) + ossl_raise(eASN1Error, "illegal EOC octets in value"); + + /* + * EOC is not really part of the content, but we required to add one + * at the end in the past. + */ + break; } - } - memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value)); - p += RSTRING_LEN(value); - /* In this case we need an additional EOC (one for the explicit part and - * one for the Constructive itself. The EOC for the Constructive is - * supplied by the user, but that for the "explicit wrapper" must be - * added here. - */ - if (explicit && inf_length == Qtrue) { - ASN1_put_eoc(&p); + item = ossl_to_der_if_possible(item); + StringValue(item); + rb_str_append(str, item); } - ossl_str_adjust(str, p); - return str; + return to_der_internal(self, 1, indef_len, str); } /* * call-seq: * asn1_ary.each { |asn1| block } => asn1_ary * - * Calls <i>block</i> once for each element in +self+, passing that element - * as parameter +asn1+. If no block is given, an enumerator is returned + * 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 @@ -1300,8 +1225,8 @@ ossl_asn1cons_each(VALUE self) * call-seq: * OpenSSL::ASN1::ObjectId.register(object_id, short_name, long_name) * - * This adds a new ObjectId to the internal tables. Where +object_id+ is the - * numerical form, +short_name+ is the short name, and +long_name+ is the long + * This adds a new ObjectId to the internal tables. Where _object_id_ is the + * numerical form, _short_name_ is the short name, and _long_name_ is the long * name. * * Returns +true+ if successful. Raises an OpenSSL::ASN1::ASN1Error if it fails. @@ -1320,14 +1245,13 @@ ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln) return Qtrue; } -/* Document-method: OpenSSL::ASN1::ObjectId#sn +/* + * call-seq: + * oid.sn -> string + * oid.short_name -> string * * The short name of the ObjectId, as defined in <openssl/objects.h>. */ -/* Document-method: OpenSSL::ASN1::ObjectId#short_name - * - * +short_name+ is an alias to +sn+ - */ static VALUE ossl_asn1obj_get_sn(VALUE self) { @@ -1341,14 +1265,13 @@ ossl_asn1obj_get_sn(VALUE self) return ret; } -/* Document-method: OpenSSL::ASN1::ObjectId#ln +/* + * call-seq: + * oid.ln -> string + * oid.long_name -> string * * The long name of the ObjectId, as defined in <openssl/objects.h>. */ -/* Document-method: OpenSSL::ASN1::ObjectId#long_name - * - * +long_name+ is an alias to +ln+ - */ static VALUE ossl_asn1obj_get_ln(VALUE self) { @@ -1362,23 +1285,48 @@ ossl_asn1obj_get_ln(VALUE self) return ret; } -/* Document-method: OpenSSL::ASN1::ObjectId#oid +static VALUE +asn1obj_get_oid_i(VALUE vobj) +{ + ASN1_OBJECT *a1obj = (void *)vobj; + VALUE str; + int len; + + str = rb_usascii_str_new(NULL, 127); + len = OBJ_obj2txt(RSTRING_PTR(str), RSTRING_LENINT(str), a1obj, 1); + if (len <= 0 || len == INT_MAX) + ossl_raise(eASN1Error, "OBJ_obj2txt"); + if (len > RSTRING_LEN(str)) { + /* +1 is for the \0 terminator added by OBJ_obj2txt() */ + rb_str_resize(str, len + 1); + len = OBJ_obj2txt(RSTRING_PTR(str), len + 1, a1obj, 1); + if (len <= 0) + ossl_raise(eASN1Error, "OBJ_obj2txt"); + } + rb_str_set_len(str, len); + return str; +} + +/* + * call-seq: + * oid.oid -> string * - * The object identifier as a +String+, e.g. "1.2.3.4.5" + * Returns a String representing the Object Identifier in the dot notation, + * e.g. "1.2.3.4.5" */ static VALUE ossl_asn1obj_get_oid(VALUE self) { - VALUE val; + VALUE str; ASN1_OBJECT *a1obj; - char buf[128]; + int state; - val = ossl_asn1_get_value(self); - a1obj = obj_to_asn1obj(val); - OBJ_obj2txt(buf, sizeof(buf), a1obj, 1); + a1obj = obj_to_asn1obj(ossl_asn1_get_value(self)); + str = rb_protect(asn1obj_get_oid_i, (VALUE)a1obj, &state); ASN1_OBJECT_free(a1obj); - - return rb_str_new2(buf); + if (state) + rb_jump_tag(state); + return str; } #define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \ @@ -1431,7 +1379,7 @@ Init_ossl_asn1(void) sivTAG = rb_intern("@tag"); sivTAGGING = rb_intern("@tagging"); sivTAG_CLASS = rb_intern("@tag_class"); - sivINFINITE_LENGTH = rb_intern("@infinite_length"); + sivINDEFINITE_LENGTH = rb_intern("@indefinite_length"); sivUNUSED_BITS = rb_intern("@unused_bits"); /* @@ -1457,24 +1405,21 @@ Init_ossl_asn1(void) * == ASN.1 class hierarchy * * The base class representing ASN.1 structures is ASN1Data. ASN1Data offers - * attributes to read and set the +tag+, the +tag_class+ and finally the - * +value+ of a particular ASN.1 item. Upon parsing, any tagged values + * attributes to read and set the _tag_, the _tag_class_ and finally the + * _value_ of a particular ASN.1 item. Upon parsing, any tagged values * (implicit or explicit) will be represented by ASN1Data instances because * their "real type" can only be determined using out-of-band information * from the ASN.1 type declaration. Since this information is normally * known when encoding a type, all sub-classes of ASN1Data offer an - * additional attribute +tagging+ that allows to encode a value implicitly + * additional attribute _tagging_ that allows to encode a value implicitly * (+:IMPLICIT+) or explicitly (+:EXPLICIT+). * * === Constructive * * Constructive is, as its name implies, the base class for all * constructed encodings, i.e. those that consist of several values, - * opposed to "primitive" encodings with just one single value. - * Primitive values that are encoded with "infinite length" are typically - * constructed (their values come in multiple chunks) and are therefore - * represented by instances of Constructive. The value of an Constructive - * is always an Array. + * opposed to "primitive" encodings with just one single value. The value of + * an Constructive is always an Array. * * ==== ASN1::Set and ASN1::Sequence * @@ -1491,18 +1436,18 @@ Init_ossl_asn1(void) * Please cf. Primitive documentation for details on sub-classes and * their respective mappings of ASN.1 data types to Ruby objects. * - * == Possible values for +tagging+ + * == Possible values for _tagging_ * * When constructing an ASN1Data object the ASN.1 type definition may * require certain elements to be either implicitly or explicitly tagged. - * This can be achieved by setting the +tagging+ attribute manually for + * This can be achieved by setting the _tagging_ attribute manually for * sub-classes of ASN1Data. Use the symbol +:IMPLICIT+ for implicit * tagging and +:EXPLICIT+ if the element requires explicit tagging. * - * == Possible values for +tag_class+ + * == Possible values for _tag_class_ * * It is possible to create arbitrary ASN1Data objects that also support - * a PRIVATE or APPLICATION tag class. Possible values for the +tag_class+ + * a PRIVATE or APPLICATION tag class. Possible values for the _tag_class_ * attribute are: * * +:UNIVERSAL+ (the default for untagged values) * * +:CONTEXT_SPECIFIC+ (the default for tagged values) @@ -1604,9 +1549,9 @@ Init_ossl_asn1(void) * * An implicitly 1-tagged INTEGER value will be parsed as an * ASN1Data with - * * +tag+ equal to 1 - * * +tag_class+ equal to +:CONTEXT_SPECIFIC+ - * * +value+ equal to a +String+ that carries the raw encoding + * * _tag_ equal to 1 + * * _tag_class_ equal to +:CONTEXT_SPECIFIC+ + * * _value_ equal to a String that carries the raw encoding * of the INTEGER. * This implies that a subsequent decoding step is required to * completely decode implicitly tagged values. @@ -1615,9 +1560,9 @@ Init_ossl_asn1(void) * * An explicitly 1-tagged INTEGER value will be parsed as an * ASN1Data with - * * +tag+ equal to 1 - * * +tag_class+ equal to +:CONTEXT_SPECIFIC+ - * * +value+ equal to an +Array+ with one single element, an + * * _tag_ equal to 1 + * * _tag_class_ equal to +:CONTEXT_SPECIFIC+ + * * _value_ equal to an Array with one single element, an * instance of OpenSSL::ASN1::Integer, i.e. the inner element * is the non-tagged primitive value, and the tagging is represented * in the outer ASN1Data @@ -1628,13 +1573,13 @@ Init_ossl_asn1(void) * der = seq.to_der * asn1 = OpenSSL::ASN1.decode(der) * # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0 - * # @infinite_length=false, + * # @indefinite_length=false, * # @tag=16, * # @tag_class=:UNIVERSAL, * # @tagging=nil, * # @value= * # [#<OpenSSL::ASN1::ASN1Data:0x87326f4 - * # @infinite_length=false, + * # @indefinite_length=false, * # @tag=0, * # @tag_class=:CONTEXT_SPECIFIC, * # @value="\x01">]> @@ -1651,18 +1596,18 @@ Init_ossl_asn1(void) * der = seq.to_der * asn1 = OpenSSL::ASN1.decode(der) * # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0 - * # @infinite_length=false, + * # @indefinite_length=false, * # @tag=16, * # @tag_class=:UNIVERSAL, * # @tagging=nil, * # @value= * # [#<OpenSSL::ASN1::ASN1Data:0x87326f4 - * # @infinite_length=false, + * # @indefinite_length=false, * # @tag=0, * # @tag_class=:CONTEXT_SPECIFIC, * # @value= * # [#<OpenSSL::ASN1::Integer:0x85bf308 - * # @infinite_length=false, + * # @indefinite_length=false, * # @tag=2, * # @tag_class=:UNIVERSAL * # @tagging=nil, @@ -1678,73 +1623,75 @@ Init_ossl_asn1(void) */ rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0); /* - * A +Number+ representing the tag number of this ASN1Data. Never +nil+. + * An Integer representing the tag number of this ASN1Data. Never +nil+. */ rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0); /* - * A +Symbol+ representing the tag class of this ASN1Data. Never +nil+. + * A Symbol representing the tag class of this ASN1Data. Never +nil+. * See ASN1Data for possible values. */ rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0); /* - * Never +nil+. A +Boolean+ indicating whether the encoding was infinite - * length (in the case of parsing) or whether an infinite length encoding - * shall be used (in the encoding case). - * In DER, every value has a finite length associated with it. But in - * scenarios where large amounts of data need to be transferred it - * might be desirable to have some kind of streaming support available. + * 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. Infinite length encodings are always constructed. + * 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 infinite length + * (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). */ - rb_attr(cASN1Data, rb_intern("infinite_length"), 1, 1, 0); + rb_attr(cASN1Data, rb_intern("indefinite_length"), 1, 1, 0); + rb_define_alias(cASN1Data, "infinite_length", "indefinite_length"); + rb_define_alias(cASN1Data, "infinite_length=", "indefinite_length="); rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3); rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0); /* Document-class: OpenSSL::ASN1::Primitive * * The parent class for all primitive encodings. Attributes are the same as - * for ASN1Data, with the addition of +tagging+. - * Primitive values can never be infinite length encodings, thus it is not - * possible to set the +infinite_length+ attribute for Primitive and its - * sub-classes. + * for ASN1Data, with the addition of _tagging_. + * Primitive values can never be encoded with indefinite length form, thus + * it is not possible to set the _indefinite_length_ attribute for Primitive + * and its sub-classes. * * == Primitive sub-classes and their mapping to Ruby classes - * * OpenSSL::ASN1::EndOfContent <=> +value+ is always +nil+ - * * OpenSSL::ASN1::Boolean <=> +value+ is a +Boolean+ - * * OpenSSL::ASN1::Integer <=> +value+ is a +Number+ - * * OpenSSL::ASN1::BitString <=> +value+ is a +String+ - * * OpenSSL::ASN1::OctetString <=> +value+ is a +String+ - * * OpenSSL::ASN1::Null <=> +value+ is always +nil+ - * * OpenSSL::ASN1::Object <=> +value+ is a +String+ - * * OpenSSL::ASN1::Enumerated <=> +value+ is a +Number+ - * * OpenSSL::ASN1::UTF8String <=> +value+ is a +String+ - * * OpenSSL::ASN1::NumericString <=> +value+ is a +String+ - * * OpenSSL::ASN1::PrintableString <=> +value+ is a +String+ - * * OpenSSL::ASN1::T61String <=> +value+ is a +String+ - * * OpenSSL::ASN1::VideotexString <=> +value+ is a +String+ - * * OpenSSL::ASN1::IA5String <=> +value+ is a +String+ - * * OpenSSL::ASN1::UTCTime <=> +value+ is a +Time+ - * * OpenSSL::ASN1::GeneralizedTime <=> +value+ is a +Time+ - * * OpenSSL::ASN1::GraphicString <=> +value+ is a +String+ - * * OpenSSL::ASN1::ISO64String <=> +value+ is a +String+ - * * OpenSSL::ASN1::GeneralString <=> +value+ is a +String+ - * * OpenSSL::ASN1::UniversalString <=> +value+ is a +String+ - * * OpenSSL::ASN1::BMPString <=> +value+ is a +String+ + * * OpenSSL::ASN1::EndOfContent <=> _value_ is always +nil+ + * * OpenSSL::ASN1::Boolean <=> _value_ is +true+ or +false+ + * * OpenSSL::ASN1::Integer <=> _value_ is an Integer + * * OpenSSL::ASN1::BitString <=> _value_ is a String + * * OpenSSL::ASN1::OctetString <=> _value_ is a String + * * OpenSSL::ASN1::Null <=> _value_ is always +nil+ + * * OpenSSL::ASN1::Object <=> _value_ is a String + * * OpenSSL::ASN1::Enumerated <=> _value_ is an Integer + * * OpenSSL::ASN1::UTF8String <=> _value_ is a String + * * OpenSSL::ASN1::NumericString <=> _value_ is a String + * * OpenSSL::ASN1::PrintableString <=> _value_ is a String + * * OpenSSL::ASN1::T61String <=> _value_ is a String + * * OpenSSL::ASN1::VideotexString <=> _value_ is a String + * * OpenSSL::ASN1::IA5String <=> _value_ is a String + * * OpenSSL::ASN1::UTCTime <=> _value_ is a Time + * * OpenSSL::ASN1::GeneralizedTime <=> _value_ is a Time + * * OpenSSL::ASN1::GraphicString <=> _value_ is a String + * * OpenSSL::ASN1::ISO64String <=> _value_ is a String + * * OpenSSL::ASN1::GeneralString <=> _value_ is a String + * * OpenSSL::ASN1::UniversalString <=> _value_ is a String + * * OpenSSL::ASN1::BMPString <=> _value_ is a String * * == OpenSSL::ASN1::BitString * * === Additional attributes - * +unused_bits+: if the underlying BIT STRING's - * length is a multiple of 8 then +unused_bits+ is 0. Otherwise - * +unused_bits+ indicates the number of bits that are to be ignored in - * the final octet of the +BitString+'s +value+. + * _unused_bits_: if the underlying BIT STRING's + * length is a multiple of 8 then _unused_bits_ is 0. Otherwise + * _unused_bits_ indicates the number of bits that are to be ignored in + * the final octet of the BitString's _value_. * * == OpenSSL::ASN1::ObjectId * @@ -1753,15 +1700,15 @@ Init_ossl_asn1(void) * parsed ASN1 encodings. * * === Additional attributes - * * +sn+: the short name as defined in <openssl/objects.h>. - * * +ln+: the long name as defined in <openssl/objects.h>. - * * +oid+: the object identifier as a +String+, e.g. "1.2.3.4.5" - * * +short_name+: alias for +sn+. - * * +long_name+: alias for +ln+. + * * _sn_: the short name as defined in <openssl/objects.h>. + * * _ln_: the long name as defined in <openssl/objects.h>. + * * _oid_: the object identifier as a String, e.g. "1.2.3.4.5" + * * _short_name_: alias for _sn_. + * * _long_name_: alias for _ln_. * * == Examples * With the Exception of OpenSSL::ASN1::EndOfContent, each Primitive class - * constructor takes at least one parameter, the +value+. + * constructor takes at least one parameter, the _value_. * * === Creating EndOfContent * eoc = OpenSSL::ASN1::EndOfContent.new @@ -1775,19 +1722,20 @@ Init_ossl_asn1(void) /* * 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 + * _tagging_ is not set when a ASN.1 structure is parsed using * OpenSSL::ASN1.decode. */ rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue); + rb_undef_method(cASN1Primitive, "indefinite_length="); rb_undef_method(cASN1Primitive, "infinite_length="); rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1); rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0); /* Document-class: OpenSSL::ASN1::Constructive * - * The parent class for all constructed encodings. The +value+ attribute - * of a Constructive is always an +Array+. Attributes are the same as - * for ASN1Data, with the addition of +tagging+. + * The parent class for all constructed encodings. The _value_ attribute + * of a Constructive is always an Array. Attributes are the same as + * for ASN1Data, with the addition of _tagging_. * * == SET and SEQUENCE * @@ -1809,48 +1757,13 @@ Init_ossl_asn1(void) * int = OpenSSL::ASN1::Integer.new(1) * str = OpenSSL::ASN1::PrintableString.new('abc') * set = OpenSSL::ASN1::Set.new( [ int, str ] ) - * - * == Infinite length primitive values - * - * The only case where Constructive is used directly is for infinite - * length encodings of primitive values. These encodings are always - * constructed, with the contents of the +value+ +Array+ being either - * UNIVERSAL non-infinite length partial encodings of the actual value - * or again constructive encodings with infinite length (i.e. infinite - * length primitive encodings may be constructed recursively with another - * infinite length value within an already infinite length value). Each - * partial encoding must be of the same UNIVERSAL type as the overall - * encoding. The value of the overall encoding consists of the - * concatenation of each partial encoding taken in sequence. The +value+ - * array of the outer infinite length value must end with a - * OpenSSL::ASN1::EndOfContent instance. - * - * Please note that it is not possible to encode Constructive without - * the +infinite_length+ attribute being set to +true+, use - * OpenSSL::ASN1::Sequence or OpenSSL::ASN1::Set in these cases instead. - * - * === Example - Infinite length OCTET STRING - * partial1 = OpenSSL::ASN1::OctetString.new("\x01") - * partial2 = OpenSSL::ASN1::OctetString.new("\x02") - * inf_octets = OpenSSL::ASN1::Constructive.new( [ partial1, - * partial2, - * OpenSSL::ASN1::EndOfContent.new ], - * OpenSSL::ASN1::OCTET_STRING, - * nil, - * :UNIVERSAL ) - * # The real value of inf_octets is "\x01\x02", i.e. the concatenation - * # of partial1 and partial2 - * inf_octets.infinite_length = true - * der = inf_octets.to_der - * asn1 = OpenSSL::ASN1.decode(der) - * puts asn1.infinite_length # => true */ cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data); rb_include_module(cASN1Constructive, rb_mEnumerable); /* * 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 + * _tagging_ is not set when a ASN.1 structure is parsed using * OpenSSL::ASN1.decode. */ rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue); @@ -1907,6 +1820,7 @@ do{\ rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0); rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0); + rb_define_method(cASN1EndOfContent, "to_der", ossl_asn1eoc_to_der, 0); class_tag_map = rb_hash_new(); rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC)); |