rubysl-openssl 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -6
  3. data/ext/rubysl/openssl/.gitignore +3 -0
  4. data/ext/rubysl/openssl/deprecation.rb +21 -0
  5. data/ext/rubysl/openssl/extconf.rb +45 -32
  6. data/ext/rubysl/openssl/openssl_missing.c +20 -7
  7. data/ext/rubysl/openssl/openssl_missing.h +22 -15
  8. data/ext/rubysl/openssl/ossl.c +610 -61
  9. data/ext/rubysl/openssl/ossl.h +31 -17
  10. data/ext/rubysl/openssl/ossl_asn1.c +974 -183
  11. data/ext/rubysl/openssl/ossl_asn1.h +3 -3
  12. data/ext/rubysl/openssl/ossl_bio.c +4 -3
  13. data/ext/rubysl/openssl/ossl_bio.h +1 -1
  14. data/ext/rubysl/openssl/ossl_bn.c +32 -28
  15. data/ext/rubysl/openssl/ossl_bn.h +1 -1
  16. data/ext/rubysl/openssl/ossl_cipher.c +494 -93
  17. data/ext/rubysl/openssl/ossl_cipher.h +1 -1
  18. data/ext/rubysl/openssl/ossl_config.c +4 -5
  19. data/ext/rubysl/openssl/ossl_config.h +1 -1
  20. data/ext/rubysl/openssl/ossl_digest.c +206 -24
  21. data/ext/rubysl/openssl/ossl_digest.h +1 -1
  22. data/ext/rubysl/openssl/ossl_engine.c +48 -26
  23. data/ext/rubysl/openssl/ossl_engine.h +1 -1
  24. data/ext/rubysl/openssl/ossl_hmac.c +40 -38
  25. data/ext/rubysl/openssl/ossl_hmac.h +1 -1
  26. data/ext/rubysl/openssl/ossl_ns_spki.c +157 -25
  27. data/ext/rubysl/openssl/ossl_ns_spki.h +1 -1
  28. data/ext/rubysl/openssl/ossl_ocsp.c +57 -40
  29. data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
  30. data/ext/rubysl/openssl/ossl_pkcs12.c +15 -13
  31. data/ext/rubysl/openssl/ossl_pkcs12.h +1 -1
  32. data/ext/rubysl/openssl/ossl_pkcs5.c +108 -18
  33. data/ext/rubysl/openssl/ossl_pkcs7.c +44 -37
  34. data/ext/rubysl/openssl/ossl_pkcs7.h +1 -1
  35. data/ext/rubysl/openssl/ossl_pkey.c +211 -15
  36. data/ext/rubysl/openssl/ossl_pkey.h +19 -9
  37. data/ext/rubysl/openssl/ossl_pkey_dh.c +180 -47
  38. data/ext/rubysl/openssl/ossl_pkey_dsa.c +184 -47
  39. data/ext/rubysl/openssl/ossl_pkey_ec.c +177 -93
  40. data/ext/rubysl/openssl/ossl_pkey_rsa.c +209 -102
  41. data/ext/rubysl/openssl/ossl_rand.c +15 -15
  42. data/ext/rubysl/openssl/ossl_rand.h +1 -1
  43. data/ext/rubysl/openssl/ossl_ssl.c +939 -192
  44. data/ext/rubysl/openssl/ossl_ssl.h +6 -6
  45. data/ext/rubysl/openssl/ossl_ssl_session.c +78 -62
  46. data/ext/rubysl/openssl/ossl_version.h +2 -2
  47. data/ext/rubysl/openssl/ossl_x509.c +1 -1
  48. data/ext/rubysl/openssl/ossl_x509.h +1 -1
  49. data/ext/rubysl/openssl/ossl_x509attr.c +20 -19
  50. data/ext/rubysl/openssl/ossl_x509cert.c +169 -67
  51. data/ext/rubysl/openssl/ossl_x509crl.c +41 -39
  52. data/ext/rubysl/openssl/ossl_x509ext.c +51 -38
  53. data/ext/rubysl/openssl/ossl_x509name.c +139 -29
  54. data/ext/rubysl/openssl/ossl_x509req.c +42 -40
  55. data/ext/rubysl/openssl/ossl_x509revoked.c +20 -20
  56. data/ext/rubysl/openssl/ossl_x509store.c +99 -47
  57. data/ext/rubysl/openssl/ruby_missing.h +3 -16
  58. data/lib/openssl/bn.rb +19 -19
  59. data/lib/openssl/buffering.rb +222 -14
  60. data/lib/openssl/cipher.rb +20 -20
  61. data/lib/openssl/config.rb +1 -4
  62. data/lib/openssl/digest.rb +47 -19
  63. data/lib/openssl/ssl.rb +197 -1
  64. data/lib/openssl/x509.rb +162 -1
  65. data/lib/rubysl/openssl.rb +4 -8
  66. data/lib/rubysl/openssl/version.rb +1 -1
  67. data/rubysl-openssl.gemspec +1 -2
  68. metadata +16 -34
  69. data/ext/rubysl/openssl/extconf.h +0 -50
  70. data/lib/openssl/net/ftptls.rb +0 -53
  71. data/lib/openssl/net/telnets.rb +0 -251
  72. data/lib/openssl/pkcs7.rb +0 -25
  73. data/lib/openssl/ssl-internal.rb +0 -187
  74. data/lib/openssl/x509-internal.rb +0 -153
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: ossl.h 28367 2010-06-21 09:18:59Z shyouhei $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' project
4
4
  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
5
  * All rights reserved.
@@ -29,7 +29,8 @@ extern "C" {
29
29
  # undef RFILE
30
30
  #endif
31
31
  #include <ruby.h>
32
- #include <rubyio.h>
32
+ #include <ruby/io.h>
33
+ #include <ruby/thread.h>
33
34
 
34
35
  /*
35
36
  * Check the OpenSSL version
@@ -45,12 +46,12 @@ extern "C" {
45
46
  #endif
46
47
 
47
48
  #if defined(_WIN32)
49
+ # include <openssl/e_os2.h>
48
50
  # define OSSL_NO_CONF_API 1
49
- # ifdef USE_WINSOCK2
50
- # include <winsock2.h>
51
- # else
52
- # include <winsock.h>
51
+ # if !defined(OPENSSL_SYS_WIN32)
52
+ # define OPENSSL_SYS_WIN32 1
53
53
  # endif
54
+ # include <winsock2.h>
54
55
  #endif
55
56
  #include <errno.h>
56
57
  #include <openssl/err.h>
@@ -74,6 +75,11 @@ extern "C" {
74
75
  # include <openssl/ocsp.h>
75
76
  #endif
76
77
 
78
+ /* OpenSSL requires passwords for PEM-encoded files to be at least four
79
+ * characters long
80
+ */
81
+ #define OSSL_MIN_PWD_LEN 4
82
+
77
83
  /*
78
84
  * Common Module
79
85
  */
@@ -88,21 +94,21 @@ extern VALUE eOSSLError;
88
94
  * CheckTypes
89
95
  */
90
96
  #define OSSL_Check_Kind(obj, klass) do {\
91
- if (!rb_obj_is_kind_of(obj, klass)) {\
97
+ if (!rb_obj_is_kind_of((obj), (klass))) {\
92
98
  ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected kind of %s)",\
93
99
  rb_obj_classname(obj), rb_class2name(klass));\
94
100
  }\
95
101
  } while (0)
96
102
 
97
103
  #define OSSL_Check_Instance(obj, klass) do {\
98
- if (!rb_obj_is_instance_of(obj, klass)) {\
104
+ if (!rb_obj_is_instance_of((obj), (klass))) {\
99
105
  ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected instance of %s)",\
100
106
  rb_obj_classname(obj), rb_class2name(klass));\
101
107
  }\
102
108
  } while (0)
103
109
 
104
110
  #define OSSL_Check_Same_Class(obj1, obj2) do {\
105
- if (!rb_obj_is_instance_of(obj1, rb_obj_class(obj2))) {\
111
+ if (!rb_obj_is_instance_of((obj1), rb_obj_class(obj2))) {\
106
112
  ossl_raise(rb_eTypeError, "wrong argument type");\
107
113
  }\
108
114
  } while (0)
@@ -117,7 +123,7 @@ extern VALUE eOSSLError;
117
123
  /*
118
124
  * String to HEXString conversion
119
125
  */
120
- int string2hex(char *, int, char **, int *);
126
+ int string2hex(const unsigned char *, int, char **, int *);
121
127
 
122
128
  /*
123
129
  * Data Conversion
@@ -127,13 +133,14 @@ STACK_OF(X509) *ossl_x509_ary2sk(VALUE);
127
133
  STACK_OF(X509) *ossl_protect_x509_ary2sk(VALUE,int*);
128
134
  VALUE ossl_x509_sk2ary(STACK_OF(X509) *certs);
129
135
  VALUE ossl_x509crl_sk2ary(STACK_OF(X509_CRL) *crl);
136
+ VALUE ossl_x509name_sk2ary(STACK_OF(X509_NAME) *names);
130
137
  VALUE ossl_buf2str(char *buf, int len);
131
138
  #define ossl_str_adjust(str, p) \
132
139
  do{\
133
- int len = RSTRING_LEN(str);\
134
- int newlen = (p) - (unsigned char*)RSTRING_PTR(str);\
140
+ int len = RSTRING_LENINT(str);\
141
+ int newlen = rb_long2int((p) - (unsigned char*)RSTRING_PTR(str));\
135
142
  assert(newlen <= len);\
136
- rb_str_set_len(str, newlen);\
143
+ rb_str_set_len((str), newlen);\
137
144
  }while(0)
138
145
 
139
146
  /*
@@ -141,6 +148,13 @@ do{\
141
148
  */
142
149
  int ossl_pem_passwd_cb(char *, int, int, void *);
143
150
 
151
+ /*
152
+ * Clear BIO* with this in PEM/DER fallback scenarios to avoid decoding
153
+ * errors piling up in OpenSSL::Errors
154
+ */
155
+ #define OSSL_BIO_reset(bio) (void)BIO_reset((bio)); \
156
+ ERR_clear_error();
157
+
144
158
  /*
145
159
  * ERRor messages
146
160
  */
@@ -184,13 +198,13 @@ extern VALUE dOSSL;
184
198
  } while (0)
185
199
 
186
200
  #define OSSL_Warning(fmt, ...) do { \
187
- OSSL_Debug(fmt, ##__VA_ARGS__); \
188
- rb_warning(fmt, ##__VA_ARGS__); \
201
+ OSSL_Debug((fmt), ##__VA_ARGS__); \
202
+ rb_warning((fmt), ##__VA_ARGS__); \
189
203
  } while (0)
190
204
 
191
205
  #define OSSL_Warn(fmt, ...) do { \
192
- OSSL_Debug(fmt, ##__VA_ARGS__); \
193
- rb_warn(fmt, ##__VA_ARGS__); \
206
+ OSSL_Debug((fmt), ##__VA_ARGS__); \
207
+ rb_warn((fmt), ##__VA_ARGS__); \
194
208
  } while (0)
195
209
  #else
196
210
  void ossl_debug(const char *, ...);
@@ -10,7 +10,20 @@
10
10
  */
11
11
  #include "ossl.h"
12
12
 
13
- #include <sys/time.h>
13
+ #if defined(HAVE_SYS_TIME_H)
14
+ # include <sys/time.h>
15
+ #elif !defined(NT) && !defined(_WIN32)
16
+ struct timeval {
17
+ long tv_sec; /* seconds */
18
+ long tv_usec; /* and microseconds */
19
+ };
20
+ #endif
21
+
22
+ static VALUE join_der(VALUE enumerable);
23
+ static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset,
24
+ int depth, int yield, long *num_read);
25
+ static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self);
26
+ static VALUE ossl_asn1eoc_initialize(VALUE self);
14
27
 
15
28
  /*
16
29
  * DATE conversion
@@ -20,16 +33,16 @@ asn1time_to_time(ASN1_TIME *time)
20
33
  {
21
34
  struct tm tm;
22
35
  VALUE argv[6];
23
-
36
+
24
37
  if (!time || !time->data) return Qnil;
25
38
  memset(&tm, 0, sizeof(struct tm));
26
-
39
+
27
40
  switch (time->type) {
28
41
  case V_ASN1_UTCTIME:
29
- if (sscanf(time->data, "%2d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
42
+ if (sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
30
43
  &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
31
44
  ossl_raise(rb_eTypeError, "bad UTCTIME format");
32
- }
45
+ }
33
46
  if (tm.tm_year < 69) {
34
47
  tm.tm_year += 2000;
35
48
  } else {
@@ -37,10 +50,10 @@ asn1time_to_time(ASN1_TIME *time)
37
50
  }
38
51
  break;
39
52
  case V_ASN1_GENERALIZEDTIME:
40
- if (sscanf(time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
53
+ if (sscanf((const char *)time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
41
54
  &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
42
55
  ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" );
43
- }
56
+ }
44
57
  break;
45
58
  default:
46
59
  rb_warning("unknown time format");
@@ -73,7 +86,7 @@ time_to_time_t(VALUE time)
73
86
  VALUE
74
87
  asn1str_to_str(ASN1_STRING *str)
75
88
  {
76
- return rb_str_new(str->data, str->length);
89
+ return rb_str_new((const char *)str->data, str->length);
77
90
  }
78
91
 
79
92
  /*
@@ -136,11 +149,16 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
136
149
  ASN1_INTEGER *
137
150
  num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
138
151
  {
139
- BIGNUM *bn = GetBNPtr(obj);
140
-
141
- if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
152
+ BIGNUM *bn;
153
+
154
+ if (NIL_P(obj))
155
+ ossl_raise(rb_eTypeError, "Can't convert nil into Integer");
156
+
157
+ bn = GetBNPtr(obj);
158
+
159
+ if (!(ai = BN_to_ASN1_INTEGER(bn, ai)))
142
160
  ossl_raise(eOSSLError, NULL);
143
- }
161
+
144
162
  return ai;
145
163
  }
146
164
  #endif
@@ -149,15 +167,17 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
149
167
  /*
150
168
  * ASN1 module
151
169
  */
152
- #define ossl_asn1_get_value(o) rb_attr_get((o),rb_intern("@value"))
153
- #define ossl_asn1_get_tag(o) rb_attr_get((o),rb_intern("@tag"))
154
- #define ossl_asn1_get_tagging(o) rb_attr_get((o),rb_intern("@tagging"))
155
- #define ossl_asn1_get_tag_class(o) rb_attr_get((o),rb_intern("@tag_class"))
156
-
157
- #define ossl_asn1_set_value(o,v) rb_iv_set((o),"@value",(v))
158
- #define ossl_asn1_set_tag(o,v) rb_iv_set((o),"@tag",(v))
159
- #define ossl_asn1_set_tagging(o,v) rb_iv_set((o),"@tagging",(v))
160
- #define ossl_asn1_set_tag_class(o,v) rb_iv_set((o),"@tag_class",(v))
170
+ #define ossl_asn1_get_value(o) rb_attr_get((o),sivVALUE)
171
+ #define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG)
172
+ #define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING)
173
+ #define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS)
174
+ #define ossl_asn1_get_infinite_length(o) rb_attr_get((o),sivINFINITE_LENGTH)
175
+
176
+ #define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v))
177
+ #define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v))
178
+ #define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v))
179
+ #define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v))
180
+ #define ossl_asn1_set_infinite_length(o,v) rb_ivar_set((o),sivINFINITE_LENGTH,(v))
161
181
 
162
182
  VALUE mASN1;
163
183
  VALUE eASN1Error;
@@ -166,6 +186,7 @@ VALUE cASN1Data;
166
186
  VALUE cASN1Primitive;
167
187
  VALUE cASN1Constructive;
168
188
 
189
+ VALUE cASN1EndOfContent;
169
190
  VALUE cASN1Boolean; /* BOOLEAN */
170
191
  VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
171
192
  VALUE cASN1BitString; /* BIT STRING */
@@ -182,6 +203,20 @@ VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
182
203
 
183
204
  static ID sIMPLICIT, sEXPLICIT;
184
205
  static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
206
+ static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINFINITE_LENGTH, sivUNUSED_BITS;
207
+
208
+ /*
209
+ * We need to implement these for backward compatibility
210
+ * reasons, behavior of ASN1_put_object and ASN1_object_size
211
+ * for infinite length values is different in OpenSSL <= 0.9.7
212
+ */
213
+ #if OPENSSL_VERSION_NUMBER < 0x00908000L
214
+ #define ossl_asn1_object_size(cons, len, tag) (cons) == 2 ? (len) + ASN1_object_size((cons), 0, (tag)) : ASN1_object_size((cons), (len), (tag))
215
+ #define ossl_asn1_put_object(pp, cons, len, tag, xc) (cons) == 2 ? ASN1_put_object((pp), (cons), 0, (tag), (xc)) : ASN1_put_object((pp), (cons), (len), (tag), (xc))
216
+ #else
217
+ #define ossl_asn1_object_size(cons, len, tag) ASN1_object_size((cons), (len), (tag))
218
+ #define ossl_asn1_put_object(pp, cons, len, tag, xc) ASN1_put_object((pp), (cons), (len), (tag), (xc))
219
+ #endif
185
220
 
186
221
  /*
187
222
  * Ruby to ASN1 converters
@@ -189,6 +224,9 @@ static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
189
224
  static ASN1_BOOLEAN
190
225
  obj_to_asn1bool(VALUE obj)
191
226
  {
227
+ if (NIL_P(obj))
228
+ ossl_raise(rb_eTypeError, "Can't convert nil into Boolean");
229
+
192
230
  #if OPENSSL_VERSION_NUMBER < 0x00907000L
193
231
  return RTEST(obj) ? 0xff : 0x100;
194
232
  #else
@@ -211,7 +249,7 @@ obj_to_asn1bstr(VALUE obj, long unused_bits)
211
249
  StringValue(obj);
212
250
  if(!(bstr = ASN1_BIT_STRING_new()))
213
251
  ossl_raise(eASN1Error, NULL);
214
- ASN1_BIT_STRING_set(bstr, RSTRING_PTR(obj), RSTRING_LEN(obj));
252
+ ASN1_BIT_STRING_set(bstr, (unsigned char *)RSTRING_PTR(obj), RSTRING_LENINT(obj));
215
253
  bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
216
254
  bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
217
255
 
@@ -226,7 +264,7 @@ obj_to_asn1str(VALUE obj)
226
264
  StringValue(obj);
227
265
  if(!(str = ASN1_STRING_new()))
228
266
  ossl_raise(eASN1Error, NULL);
229
- ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LEN(obj));
267
+ ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LENINT(obj));
230
268
 
231
269
  return str;
232
270
  }
@@ -292,7 +330,7 @@ obj_to_asn1derstr(VALUE obj)
292
330
  str = ossl_to_der(obj);
293
331
  if(!(a1str = ASN1_STRING_new()))
294
332
  ossl_raise(eASN1Error, NULL);
295
- ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LEN(str));
333
+ ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LENINT(str));
296
334
 
297
335
  return a1str;
298
336
  }
@@ -301,10 +339,10 @@ obj_to_asn1derstr(VALUE obj)
301
339
  * DER to Ruby converters
302
340
  */
303
341
  static VALUE
304
- decode_bool(unsigned char* der, int length)
342
+ decode_bool(unsigned char* der, long length)
305
343
  {
306
344
  int val;
307
- unsigned const char *p;
345
+ const unsigned char *p;
308
346
 
309
347
  p = der;
310
348
  if((val = d2i_ASN1_BOOLEAN(NULL, &p, length)) < 0)
@@ -314,11 +352,11 @@ decode_bool(unsigned char* der, int length)
314
352
  }
315
353
 
316
354
  static VALUE
317
- decode_int(unsigned char* der, int length)
355
+ decode_int(unsigned char* der, long length)
318
356
  {
319
357
  ASN1_INTEGER *ai;
320
- unsigned const char *p;
321
- VALUE ret;
358
+ const unsigned char *p;
359
+ VALUE ret;
322
360
  int status = 0;
323
361
 
324
362
  p = der;
@@ -333,7 +371,7 @@ decode_int(unsigned char* der, int length)
333
371
  }
334
372
 
335
373
  static VALUE
336
- decode_bstr(unsigned char* der, int length, long *unused_bits)
374
+ decode_bstr(unsigned char* der, long length, long *unused_bits)
337
375
  {
338
376
  ASN1_BIT_STRING *bstr;
339
377
  const unsigned char *p;
@@ -354,11 +392,11 @@ decode_bstr(unsigned char* der, int length, long *unused_bits)
354
392
  }
355
393
 
356
394
  static VALUE
357
- decode_enum(unsigned char* der, int length)
395
+ decode_enum(unsigned char* der, long length)
358
396
  {
359
397
  ASN1_ENUMERATED *ai;
360
- unsigned const char *p;
361
- VALUE ret;
398
+ const unsigned char *p;
399
+ VALUE ret;
362
400
  int status = 0;
363
401
 
364
402
  p = der;
@@ -373,10 +411,10 @@ decode_enum(unsigned char* der, int length)
373
411
  }
374
412
 
375
413
  static VALUE
376
- decode_null(unsigned char* der, int length)
414
+ decode_null(unsigned char* der, long length)
377
415
  {
378
416
  ASN1_NULL *null;
379
- unsigned char const *p;
417
+ const unsigned char *p;
380
418
 
381
419
  p = der;
382
420
  if(!(null = d2i_ASN1_NULL(NULL, &p, length)))
@@ -387,10 +425,10 @@ decode_null(unsigned char* der, int length)
387
425
  }
388
426
 
389
427
  static VALUE
390
- decode_obj(unsigned char* der, int length)
428
+ decode_obj(unsigned char* der, long length)
391
429
  {
392
430
  ASN1_OBJECT *obj;
393
- unsigned const char *p;
431
+ const unsigned char *p;
394
432
  VALUE ret;
395
433
  int nid;
396
434
  BIO *bio;
@@ -416,10 +454,10 @@ decode_obj(unsigned char* der, int length)
416
454
  }
417
455
 
418
456
  static VALUE
419
- decode_time(unsigned char* der, int length)
457
+ decode_time(unsigned char* der, long length)
420
458
  {
421
459
  ASN1_TIME *time;
422
- unsigned const char *p;
460
+ const unsigned char *p;
423
461
  VALUE ret;
424
462
  int status = 0;
425
463
 
@@ -434,6 +472,15 @@ decode_time(unsigned char* der, int length)
434
472
  return ret;
435
473
  }
436
474
 
475
+ static VALUE
476
+ decode_eoc(unsigned char *der, long length)
477
+ {
478
+ if (length != 2 || !(der[0] == 0x00 && der[1] == 0x00))
479
+ ossl_raise(eASN1Error, NULL);
480
+
481
+ return rb_str_new("", 0);
482
+ }
483
+
437
484
  /********/
438
485
 
439
486
  typedef struct {
@@ -442,7 +489,7 @@ typedef struct {
442
489
  } ossl_asn1_info_t;
443
490
 
444
491
  static ossl_asn1_info_t ossl_asn1_info[] = {
445
- { "EOC", NULL, }, /* 0 */
492
+ { "EOC", &cASN1EndOfContent, }, /* 0 */
446
493
  { "BOOLEAN", &cASN1Boolean, }, /* 1 */
447
494
  { "INTEGER", &cASN1Integer, }, /* 2 */
448
495
  { "BIT_STRING", &cASN1BitString, }, /* 3 */
@@ -477,6 +524,8 @@ static ossl_asn1_info_t ossl_asn1_info[] = {
477
524
 
478
525
  int ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]));
479
526
 
527
+ static VALUE class_tag_map;
528
+
480
529
  static int ossl_asn1_default_tag(VALUE obj);
481
530
 
482
531
  ASN1_TYPE*
@@ -486,7 +535,7 @@ ossl_asn1_get_asn1type(VALUE obj)
486
535
  VALUE value, rflag;
487
536
  void *ptr;
488
537
  void (*free_func)();
489
- long tag, flag;
538
+ int tag, flag;
490
539
 
491
540
  tag = ossl_asn1_default_tag(obj);
492
541
  value = ossl_asn1_get_value(obj);
@@ -501,7 +550,7 @@ ossl_asn1_get_asn1type(VALUE obj)
501
550
  free_func = ASN1_INTEGER_free;
502
551
  break;
503
552
  case V_ASN1_BIT_STRING:
504
- rflag = rb_attr_get(obj, rb_intern("@unused_bits"));
553
+ rflag = rb_attr_get(obj, sivUNUSED_BITS);
505
554
  flag = NIL_P(rflag) ? -1 : NUM2INT(rflag);
506
555
  ptr = obj_to_asn1bstr(value, flag);
507
556
  free_func = ASN1_BIT_STRING_free;
@@ -521,7 +570,7 @@ ossl_asn1_get_asn1type(VALUE obj)
521
570
  case V_ASN1_ISO64STRING: /* FALLTHROUGH */
522
571
  case V_ASN1_GENERALSTRING: /* FALLTHROUGH */
523
572
  case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
524
- case V_ASN1_BMPSTRING:
573
+ case V_ASN1_BMPSTRING:
525
574
  ptr = obj_to_asn1str(value);
526
575
  free_func = ASN1_STRING_free;
527
576
  break;
@@ -558,13 +607,15 @@ ossl_asn1_get_asn1type(VALUE obj)
558
607
  static int
559
608
  ossl_asn1_default_tag(VALUE obj)
560
609
  {
561
- int i;
562
-
563
- for(i = 0; i < ossl_asn1_info_size; i++){
564
- if(ossl_asn1_info[i].klass &&
565
- rb_obj_is_kind_of(obj, *ossl_asn1_info[i].klass)){
566
- return i;
567
- }
610
+ VALUE tmp_class, tag;
611
+
612
+ tmp_class = CLASS_OF(obj);
613
+ while (tmp_class) {
614
+ tag = rb_hash_lookup(class_tag_map, tmp_class);
615
+ if (tag != Qnil) {
616
+ return NUM2INT(tag);
617
+ }
618
+ tmp_class = rb_class_superclass(tmp_class);
568
619
  }
569
620
  ossl_raise(eASN1Error, "universal tag for %s not found",
570
621
  rb_class2name(CLASS_OF(obj)));
@@ -643,6 +694,22 @@ ossl_asn1_class2sym(int tc)
643
694
  return ID2SYM(sUNIVERSAL);
644
695
  }
645
696
 
697
+ /*
698
+ * call-seq:
699
+ * OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data
700
+ *
701
+ * +value+: Please have a look at Constructive and Primitive to see how Ruby
702
+ * types are mapped to ASN.1 types and vice versa.
703
+ *
704
+ * +tag+: A +Number+ indicating the tag number.
705
+ *
706
+ * +tag_class+: A +Symbol+ indicating the tag class. Please cf. ASN1 for
707
+ * possible values.
708
+ *
709
+ * == Example
710
+ * asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42)
711
+ * tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER
712
+ */
646
713
  static VALUE
647
714
  ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
648
715
  {
@@ -653,12 +720,13 @@ ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
653
720
  ossl_asn1_set_tag(self, tag);
654
721
  ossl_asn1_set_value(self, value);
655
722
  ossl_asn1_set_tag_class(self, tag_class);
723
+ ossl_asn1_set_infinite_length(self, Qfalse);
656
724
 
657
725
  return self;
658
726
  }
659
727
 
660
- static VALUE
661
- join_der_i(VALUE i, VALUE str)
728
+ static VALUE
729
+ join_der_i(VALUE i, VALUE str)
662
730
  {
663
731
  i = ossl_to_der_if_possible(i);
664
732
  StringValue(i);
@@ -674,10 +742,19 @@ join_der(VALUE enumerable)
674
742
  return str;
675
743
  }
676
744
 
745
+ /*
746
+ * call-seq:
747
+ * asn1.to_der => DER-encoded String
748
+ *
749
+ * Encodes this ASN1Data into a DER-encoded String value. The result is
750
+ * DER-encoded except for the possibility of infinite length encodings.
751
+ * Infinite length encodings are not allowed in strict DER, so strictly
752
+ * speaking the result of such an encoding would be a BER-encoding.
753
+ */
677
754
  static VALUE
678
755
  ossl_asn1data_to_der(VALUE self)
679
756
  {
680
- VALUE value, der;
757
+ VALUE value, der, inf_length;
681
758
  int tag, tag_class, is_cons = 0;
682
759
  long length;
683
760
  unsigned char *p;
@@ -691,11 +768,15 @@ ossl_asn1data_to_der(VALUE self)
691
768
 
692
769
  tag = ossl_asn1_tag(self);
693
770
  tag_class = ossl_asn1_tag_class(self);
694
- if((length = ASN1_object_size(1, RSTRING_LEN(value), tag)) <= 0)
771
+ inf_length = ossl_asn1_get_infinite_length(self);
772
+ if (inf_length == Qtrue) {
773
+ is_cons = 2;
774
+ }
775
+ if((length = ossl_asn1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0)
695
776
  ossl_raise(eASN1Error, NULL);
696
777
  der = rb_str_new(0, length);
697
- p = RSTRING_PTR(der);
698
- ASN1_put_object(&p, is_cons, RSTRING_LEN(value), tag, tag_class);
778
+ p = (unsigned char *)RSTRING_PTR(der);
779
+ ossl_asn1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class);
699
780
  memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
700
781
  p += RSTRING_LEN(value);
701
782
  ossl_str_adjust(der, p);
@@ -704,157 +785,345 @@ ossl_asn1data_to_der(VALUE self)
704
785
  }
705
786
 
706
787
  static VALUE
707
- ossl_asn1_decode0(unsigned char **pp, long length, long *offset, long depth,
708
- int once, int yield)
788
+ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
789
+ VALUE tc, long *num_read)
709
790
  {
710
- unsigned char *start, *p;
711
- long len, off = *offset;
712
- int hlen, tag, tc, j;
713
- VALUE ary, asn1data, value, tag_class;
791
+ VALUE value, asn1data;
792
+ unsigned char *p;
793
+ long flag = 0;
714
794
 
715
- ary = rb_ary_new();
716
795
  p = *pp;
717
- while(length > 0){
718
- start = p;
719
- j = ASN1_get_object((const unsigned char**)&p, &len, &tag, &tc, length);
720
- if(j & 0x80) ossl_raise(eASN1Error, NULL);
721
- hlen = p - start;
722
- if(yield){
723
- VALUE arg = rb_ary_new();
724
- rb_ary_push(arg, LONG2NUM(depth));
725
- rb_ary_push(arg, LONG2NUM(off));
726
- rb_ary_push(arg, LONG2NUM(hlen));
727
- rb_ary_push(arg, LONG2NUM(len));
728
- rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
729
- rb_ary_push(arg, ossl_asn1_class2sym(tc));
730
- rb_ary_push(arg, INT2NUM(tag));
731
- rb_yield(arg);
796
+
797
+ if(tc == sUNIVERSAL && tag < ossl_asn1_info_size) {
798
+ switch(tag){
799
+ case V_ASN1_EOC:
800
+ value = decode_eoc(p, hlen+length);
801
+ break;
802
+ case V_ASN1_BOOLEAN:
803
+ value = decode_bool(p, hlen+length);
804
+ break;
805
+ case V_ASN1_INTEGER:
806
+ value = decode_int(p, hlen+length);
807
+ break;
808
+ case V_ASN1_BIT_STRING:
809
+ value = decode_bstr(p, hlen+length, &flag);
810
+ break;
811
+ case V_ASN1_NULL:
812
+ value = decode_null(p, hlen+length);
813
+ break;
814
+ case V_ASN1_ENUMERATED:
815
+ value = decode_enum(p, hlen+length);
816
+ break;
817
+ case V_ASN1_OBJECT:
818
+ value = decode_obj(p, hlen+length);
819
+ break;
820
+ case V_ASN1_UTCTIME: /* FALLTHROUGH */
821
+ case V_ASN1_GENERALIZEDTIME:
822
+ value = decode_time(p, hlen+length);
823
+ break;
824
+ default:
825
+ /* use original value */
826
+ p += hlen;
827
+ value = rb_str_new((const char *)p, length);
828
+ break;
732
829
  }
733
- length -= hlen;
734
- off += hlen;
735
- if(len > length) ossl_raise(eASN1Error, "value is too short");
736
- if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
737
- tag_class = sPRIVATE;
738
- else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
739
- tag_class = sCONTEXT_SPECIFIC;
740
- else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
741
- tag_class = sAPPLICATION;
742
- else
743
- tag_class = sUNIVERSAL;
744
- if(j & V_ASN1_CONSTRUCTED){
745
- /* TODO: if j == 0x21 it is indefinite length object. */
746
- if((j == 0x21) && (len == 0)){
747
- long lastoff = off;
748
- value = ossl_asn1_decode0(&p, length, &off, depth+1, 0, yield);
749
- len = off - lastoff;
750
- }
751
- else value = ossl_asn1_decode0(&p, len, &off, depth+1, 0, yield);
830
+ }
831
+ else {
832
+ p += hlen;
833
+ value = rb_str_new((const char *)p, length);
834
+ }
835
+
836
+ *pp += hlen + length;
837
+ *num_read = hlen + length;
838
+
839
+ if (tc == sUNIVERSAL && tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
840
+ VALUE klass = *ossl_asn1_info[tag].klass;
841
+ VALUE args[4];
842
+ args[0] = value;
843
+ args[1] = INT2NUM(tag);
844
+ args[2] = Qnil;
845
+ args[3] = ID2SYM(tc);
846
+ asn1data = rb_obj_alloc(klass);
847
+ ossl_asn1_initialize(4, args, asn1data);
848
+ if(tag == V_ASN1_BIT_STRING){
849
+ rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag));
752
850
  }
753
- else{
754
- value = rb_str_new(p, len);
755
- p += len;
756
- off += len;
851
+ }
852
+ else {
853
+ asn1data = rb_obj_alloc(cASN1Data);
854
+ ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), ID2SYM(tc));
855
+ }
856
+
857
+ return asn1data;
858
+ }
859
+
860
+ static VALUE
861
+ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
862
+ long *offset, int depth, int yield, int j,
863
+ int tag, VALUE tc, long *num_read)
864
+ {
865
+ VALUE value, asn1data, ary;
866
+ int infinite;
867
+ long off = *offset;
868
+
869
+ infinite = (j == 0x21);
870
+ ary = rb_ary_new();
871
+
872
+ while (length > 0 || infinite) {
873
+ long inner_read = 0;
874
+ value = ossl_asn1_decode0(pp, max_len, &off, depth + 1, yield, &inner_read);
875
+ *num_read += inner_read;
876
+ max_len -= inner_read;
877
+ rb_ary_push(ary, value);
878
+ if (length > 0)
879
+ length -= inner_read;
880
+
881
+ if (infinite &&
882
+ NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC &&
883
+ SYM2ID(ossl_asn1_get_tag_class(value)) == sUNIVERSAL) {
884
+ break;
757
885
  }
758
- if(tag_class == sUNIVERSAL &&
759
- tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass){
760
- VALUE klass = *ossl_asn1_info[tag].klass;
761
- long flag = 0;
762
- if(!rb_obj_is_kind_of(value, rb_cArray)){
763
- switch(tag){
764
- case V_ASN1_BOOLEAN:
765
- value = decode_bool(start, hlen+len);
766
- break;
767
- case V_ASN1_INTEGER:
768
- value = decode_int(start, hlen+len);
769
- break;
770
- case V_ASN1_BIT_STRING:
771
- value = decode_bstr(start, hlen+len, &flag);
772
- break;
773
- case V_ASN1_NULL:
774
- value = decode_null(start, hlen+len);
775
- break;
776
- case V_ASN1_ENUMERATED:
777
- value = decode_enum(start, hlen+len);
778
- break;
779
- case V_ASN1_OBJECT:
780
- value = decode_obj(start, hlen+len);
781
- break;
782
- case V_ASN1_UTCTIME: /* FALLTHROUGH */
783
- case V_ASN1_GENERALIZEDTIME:
784
- value = decode_time(start, hlen+len);
785
- break;
786
- default:
787
- /* use original value */
788
- break;
789
- }
886
+ }
887
+
888
+ if (tc == sUNIVERSAL) {
889
+ VALUE args[4];
890
+ int not_sequence_or_set;
891
+
892
+ not_sequence_or_set = tag != V_ASN1_SEQUENCE && tag != V_ASN1_SET;
893
+
894
+ if (not_sequence_or_set) {
895
+ if (infinite) {
896
+ asn1data = rb_obj_alloc(cASN1Constructive);
790
897
  }
791
- asn1data = rb_funcall(klass, rb_intern("new"), 1, value);
792
- if(tag == V_ASN1_BIT_STRING){
793
- rb_iv_set(asn1data, "@unused_bits", LONG2NUM(flag));
898
+ else {
899
+ ossl_raise(eASN1Error, "invalid non-infinite tag");
900
+ return Qnil;
794
901
  }
795
902
  }
796
- else{
797
- asn1data = rb_funcall(cASN1Data, rb_intern("new"), 3,
798
- value, INT2NUM(tag), ID2SYM(tag_class));
903
+ else {
904
+ VALUE klass = *ossl_asn1_info[tag].klass;
905
+ asn1data = rb_obj_alloc(klass);
799
906
  }
800
- rb_ary_push(ary, asn1data);
801
- length -= len;
802
- if(once) break;
907
+ args[0] = ary;
908
+ args[1] = INT2NUM(tag);
909
+ args[2] = Qnil;
910
+ args[3] = ID2SYM(tc);
911
+ ossl_asn1_initialize(4, args, asn1data);
912
+ }
913
+ else {
914
+ asn1data = rb_obj_alloc(cASN1Data);
915
+ ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), ID2SYM(tc));
916
+ }
917
+
918
+ if (infinite)
919
+ ossl_asn1_set_infinite_length(asn1data, Qtrue);
920
+ else
921
+ ossl_asn1_set_infinite_length(asn1data, Qfalse);
922
+
923
+ *offset = off;
924
+ return asn1data;
925
+ }
926
+
927
+ static VALUE
928
+ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
929
+ int yield, long *num_read)
930
+ {
931
+ unsigned char *start, *p;
932
+ const unsigned char *p0;
933
+ long len = 0, inner_read = 0, off = *offset, hlen;
934
+ int tag, tc, j;
935
+ VALUE asn1data, tag_class;
936
+
937
+ p = *pp;
938
+ start = p;
939
+ p0 = p;
940
+ j = ASN1_get_object(&p0, &len, &tag, &tc, length);
941
+ p = (unsigned char *)p0;
942
+ if(j & 0x80) ossl_raise(eASN1Error, NULL);
943
+ if(len > length) ossl_raise(eASN1Error, "value is too short");
944
+ if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
945
+ tag_class = sPRIVATE;
946
+ else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
947
+ tag_class = sCONTEXT_SPECIFIC;
948
+ else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
949
+ tag_class = sAPPLICATION;
950
+ else
951
+ tag_class = sUNIVERSAL;
952
+
953
+ hlen = p - start;
954
+
955
+ if(yield) {
956
+ VALUE arg = rb_ary_new();
957
+ rb_ary_push(arg, LONG2NUM(depth));
958
+ rb_ary_push(arg, LONG2NUM(*offset));
959
+ rb_ary_push(arg, LONG2NUM(hlen));
960
+ rb_ary_push(arg, LONG2NUM(len));
961
+ rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
962
+ rb_ary_push(arg, ossl_asn1_class2sym(tc));
963
+ rb_ary_push(arg, INT2NUM(tag));
964
+ rb_yield(arg);
965
+ }
966
+
967
+ if(j & V_ASN1_CONSTRUCTED) {
968
+ *pp += hlen;
969
+ off += hlen;
970
+ asn1data = int_ossl_asn1_decode0_cons(pp, length, len, &off, depth, yield, j, tag, tag_class, &inner_read);
971
+ inner_read += hlen;
972
+ }
973
+ else {
974
+ if ((j & 0x01) && (len == 0)) ossl_raise(eASN1Error, "Infinite length for primitive value");
975
+ asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read);
976
+ off += hlen + len;
977
+ }
978
+ if (num_read)
979
+ *num_read = inner_read;
980
+ if (len != 0 && inner_read != hlen + len) {
981
+ ossl_raise(eASN1Error,
982
+ "Type mismatch. Bytes read: %ld Bytes available: %ld",
983
+ inner_read, hlen + len);
803
984
  }
804
- *pp = p;
985
+
805
986
  *offset = off;
987
+ return asn1data;
988
+ }
806
989
 
807
- return ary;
990
+ static void
991
+ int_ossl_decode_sanity_check(long len, long read, long offset)
992
+ {
993
+ if (len != 0 && (read != len || offset != len)) {
994
+ ossl_raise(eASN1Error,
995
+ "Type mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ld",
996
+ read, len, offset);
997
+ }
808
998
  }
809
999
 
1000
+ /*
1001
+ * call-seq:
1002
+ * OpenSSL::ASN1.traverse(asn1) -> nil
1003
+ *
1004
+ * If a block is given, it prints out each of the elements encountered.
1005
+ * Block parameters are (in that order):
1006
+ * * depth: The recursion depth, plus one with each constructed value being encountered (Number)
1007
+ * * offset: Current byte offset (Number)
1008
+ * * header length: Combined length in bytes of the Tag and Length headers. (Number)
1009
+ * * length: The overall remaining length of the entire data (Number)
1010
+ * * constructed: Whether this value is constructed or not (Boolean)
1011
+ * * tag_class: Current tag class (Symbol)
1012
+ * * tag: The current tag (Number)
1013
+ *
1014
+ * == Example
1015
+ * der = File.binread('asn1data.der')
1016
+ * OpenSSL::ASN1.traverse(der) do | depth, offset, header_len, length, constructed, tag_class, tag|
1017
+ * puts "Depth: #{depth} Offset: #{offset} Length: #{length}"
1018
+ * puts "Header length: #{header_len} Tag: #{tag} Tag class: #{tag_class} Constructed: #{constructed}"
1019
+ * end
1020
+ */
810
1021
  static VALUE
811
1022
  ossl_asn1_traverse(VALUE self, VALUE obj)
812
1023
  {
813
1024
  unsigned char *p;
814
- long offset = 0;
815
1025
  volatile VALUE tmp;
1026
+ long len, read = 0, offset = 0;
816
1027
 
817
1028
  obj = ossl_to_der_if_possible(obj);
818
1029
  tmp = rb_str_new4(StringValue(obj));
819
- p = RSTRING_PTR(tmp);
820
- ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 1);
821
-
1030
+ p = (unsigned char *)RSTRING_PTR(tmp);
1031
+ len = RSTRING_LEN(tmp);
1032
+ ossl_asn1_decode0(&p, len, &offset, 0, 1, &read);
1033
+ int_ossl_decode_sanity_check(len, read, offset);
822
1034
  return Qnil;
823
1035
  }
824
1036
 
1037
+ /*
1038
+ * call-seq:
1039
+ * OpenSSL::ASN1.decode(der) -> ASN1Data
1040
+ *
1041
+ * Decodes a BER- or DER-encoded value and creates an ASN1Data instance. +der+
1042
+ * may be a +String+ or any object that features a +#to_der+ method transforming
1043
+ * it into a BER-/DER-encoded +String+.
1044
+ *
1045
+ * == Example
1046
+ * der = File.binread('asn1data')
1047
+ * asn1 = OpenSSL::ASN1.decode(der)
1048
+ */
825
1049
  static VALUE
826
1050
  ossl_asn1_decode(VALUE self, VALUE obj)
827
1051
  {
828
- VALUE ret, ary;
1052
+ VALUE ret;
829
1053
  unsigned char *p;
830
- long offset = 0;
831
1054
  volatile VALUE tmp;
1055
+ long len, read = 0, offset = 0;
832
1056
 
833
1057
  obj = ossl_to_der_if_possible(obj);
834
1058
  tmp = rb_str_new4(StringValue(obj));
835
- p = RSTRING_PTR(tmp);
836
- ary = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 1, 0);
837
- ret = rb_ary_entry(ary, 0);
838
-
1059
+ p = (unsigned char *)RSTRING_PTR(tmp);
1060
+ len = RSTRING_LEN(tmp);
1061
+ ret = ossl_asn1_decode0(&p, len, &offset, 0, 0, &read);
1062
+ int_ossl_decode_sanity_check(len, read, offset);
839
1063
  return ret;
840
1064
  }
841
1065
 
1066
+ /*
1067
+ * call-seq:
1068
+ * OpenSSL::ASN1.decode_all(der) -> Array of ASN1Data
1069
+ *
1070
+ * Similar to +decode+ with the difference that +decode+ expects one
1071
+ * distinct value represented in +der+. +decode_all+ on the contrary
1072
+ * decodes a sequence of sequential BER/DER values lined up in +der+
1073
+ * and returns them as an array.
1074
+ *
1075
+ * == Example
1076
+ * ders = File.binread('asn1data_seq')
1077
+ * asn1_ary = OpenSSL::ASN1.decode_all(ders)
1078
+ */
842
1079
  static VALUE
843
1080
  ossl_asn1_decode_all(VALUE self, VALUE obj)
844
1081
  {
845
- VALUE ret;
1082
+ VALUE ary, val;
846
1083
  unsigned char *p;
847
- long offset = 0;
1084
+ long len, tmp_len = 0, read = 0, offset = 0;
848
1085
  volatile VALUE tmp;
849
1086
 
850
1087
  obj = ossl_to_der_if_possible(obj);
851
1088
  tmp = rb_str_new4(StringValue(obj));
852
- p = RSTRING_PTR(tmp);
853
- ret = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 0);
854
-
855
- return ret;
1089
+ p = (unsigned char *)RSTRING_PTR(tmp);
1090
+ len = RSTRING_LEN(tmp);
1091
+ tmp_len = len;
1092
+ ary = rb_ary_new();
1093
+ while (tmp_len > 0) {
1094
+ long tmp_read = 0;
1095
+ val = ossl_asn1_decode0(&p, tmp_len, &offset, 0, 0, &tmp_read);
1096
+ rb_ary_push(ary, val);
1097
+ read += tmp_read;
1098
+ tmp_len -= tmp_read;
1099
+ }
1100
+ int_ossl_decode_sanity_check(len, read, offset);
1101
+ return ary;
856
1102
  }
857
1103
 
1104
+ /*
1105
+ * call-seq:
1106
+ * OpenSSL::ASN1::Primitive.new( value [, tag, tagging, tag_class ]) => Primitive
1107
+ *
1108
+ * +value+: is mandatory.
1109
+ *
1110
+ * +tag+: optional, may be specified for tagged values. If no +tag+ is
1111
+ * specified, the UNIVERSAL tag corresponding to the Primitive sub-class
1112
+ * is used by default.
1113
+ *
1114
+ * +tagging+: may be used as an encoding hint to encode a value either
1115
+ * explicitly or implicitly, see ASN1 for possible values.
1116
+ *
1117
+ * +tag_class+: if +tag+ and +tagging+ are +nil+ then this is set to
1118
+ * +:UNIVERSAL+ by default. If either +tag+ or +tagging+ are set then
1119
+ * +:CONTEXT_SPECIFIC+ is used as the default. For possible values please
1120
+ * cf. ASN1.
1121
+ *
1122
+ * == Example
1123
+ * int = OpenSSL::ASN1::Integer.new(42)
1124
+ * zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :IMPLICIT)
1125
+ * private_explicit_zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :EXPLICIT, :PRIVATE)
1126
+ */
858
1127
  static VALUE
859
1128
  ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
860
1129
  {
@@ -864,12 +1133,14 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
864
1133
  if(argc > 1){
865
1134
  if(NIL_P(tag))
866
1135
  ossl_raise(eASN1Error, "must specify tag number");
867
- if(NIL_P(tagging))
868
- tagging = ID2SYM(sEXPLICIT);
869
- if(!SYMBOL_P(tagging))
870
- ossl_raise(eASN1Error, "invalid tag default");
871
- if(NIL_P(tag_class))
872
- tag_class = ID2SYM(sCONTEXT_SPECIFIC);
1136
+ if(!NIL_P(tagging) && !SYMBOL_P(tagging))
1137
+ ossl_raise(eASN1Error, "invalid tagging method");
1138
+ if(NIL_P(tag_class)) {
1139
+ if (NIL_P(tagging))
1140
+ tag_class = ID2SYM(sUNIVERSAL);
1141
+ else
1142
+ tag_class = ID2SYM(sCONTEXT_SPECIFIC);
1143
+ }
873
1144
  if(!SYMBOL_P(tag_class))
874
1145
  ossl_raise(eASN1Error, "invalid tag class");
875
1146
  if(SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
@@ -877,17 +1148,33 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
877
1148
  }
878
1149
  else{
879
1150
  tag = INT2NUM(ossl_asn1_default_tag(self));
880
- tagging = Qnil;
1151
+ tagging = Qnil;
881
1152
  tag_class = ID2SYM(sUNIVERSAL);
882
1153
  }
883
1154
  ossl_asn1_set_tag(self, tag);
884
1155
  ossl_asn1_set_value(self, value);
885
1156
  ossl_asn1_set_tagging(self, tagging);
886
1157
  ossl_asn1_set_tag_class(self, tag_class);
1158
+ ossl_asn1_set_infinite_length(self, Qfalse);
887
1159
 
888
1160
  return self;
889
1161
  }
890
1162
 
1163
+ static VALUE
1164
+ ossl_asn1eoc_initialize(VALUE self) {
1165
+ VALUE tag, tagging, tag_class, value;
1166
+ tag = INT2NUM(ossl_asn1_default_tag(self));
1167
+ tagging = Qnil;
1168
+ tag_class = ID2SYM(sUNIVERSAL);
1169
+ value = rb_str_new("", 0);
1170
+ ossl_asn1_set_tag(self, tag);
1171
+ ossl_asn1_set_value(self, value);
1172
+ ossl_asn1_set_tagging(self, tagging);
1173
+ ossl_asn1_set_tag_class(self, tag_class);
1174
+ ossl_asn1_set_infinite_length(self, Qfalse);
1175
+ return self;
1176
+ }
1177
+
891
1178
  static int
892
1179
  ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp)
893
1180
  {
@@ -912,6 +1199,12 @@ ossl_ASN1_TYPE_free(ASN1_TYPE *a)
912
1199
  ASN1_TYPE_free(a);
913
1200
  }
914
1201
 
1202
+ /*
1203
+ * call-seq:
1204
+ * asn1.to_der => DER-encoded String
1205
+ *
1206
+ * See ASN1Data#to_der for details. *
1207
+ */
915
1208
  static VALUE
916
1209
  ossl_asn1prim_to_der(VALUE self)
917
1210
  {
@@ -926,7 +1219,7 @@ ossl_asn1prim_to_der(VALUE self)
926
1219
  explicit = ossl_asn1_is_explicit(self);
927
1220
  asn1 = ossl_asn1_get_asn1type(self);
928
1221
 
929
- len = ASN1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn);
1222
+ len = ossl_asn1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn);
930
1223
  if(!(buf = OPENSSL_malloc(len))){
931
1224
  ossl_ASN1_TYPE_free(asn1);
932
1225
  ossl_raise(eASN1Error, "cannot alloc buffer");
@@ -935,7 +1228,7 @@ ossl_asn1prim_to_der(VALUE self)
935
1228
  if (tc == V_ASN1_UNIVERSAL) {
936
1229
  ossl_i2d_ASN1_TYPE(asn1, &p);
937
1230
  } else if (explicit) {
938
- ASN1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc);
1231
+ ossl_asn1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc);
939
1232
  ossl_i2d_ASN1_TYPE(asn1, &p);
940
1233
  } else {
941
1234
  ossl_i2d_ASN1_TYPE(asn1, &p);
@@ -944,45 +1237,113 @@ ossl_asn1prim_to_der(VALUE self)
944
1237
  ossl_ASN1_TYPE_free(asn1);
945
1238
  reallen = p - buf;
946
1239
  assert(reallen <= len);
947
- str = ossl_buf2str(buf, reallen); /* buf will be free in ossl_buf2str */
1240
+ str = ossl_buf2str((char *)buf, rb_long2int(reallen)); /* buf will be free in ossl_buf2str */
948
1241
 
949
1242
  return str;
950
1243
  }
951
1244
 
1245
+ /*
1246
+ * call-seq:
1247
+ * asn1.to_der => DER-encoded String
1248
+ *
1249
+ * See ASN1Data#to_der for details.
1250
+ */
952
1251
  static VALUE
953
1252
  ossl_asn1cons_to_der(VALUE self)
954
1253
  {
955
- int tag, tn, tc, explicit;
956
- long seq_len, length;
1254
+ int tag, tn, tc, explicit, constructed = 1;
1255
+ int found_prim = 0, seq_len;
1256
+ long length;
957
1257
  unsigned char *p;
958
- VALUE value, str;
1258
+ VALUE value, str, inf_length;
959
1259
 
960
- tag = ossl_asn1_default_tag(self);
961
1260
  tn = NUM2INT(ossl_asn1_get_tag(self));
962
1261
  tc = ossl_asn1_tag_class(self);
1262
+ inf_length = ossl_asn1_get_infinite_length(self);
1263
+ if (inf_length == Qtrue) {
1264
+ VALUE ary, example;
1265
+ constructed = 2;
1266
+ if (CLASS_OF(self) == cASN1Sequence ||
1267
+ CLASS_OF(self) == cASN1Set) {
1268
+ tag = ossl_asn1_default_tag(self);
1269
+ }
1270
+ else { /* must be a constructive encoding of a primitive value */
1271
+ ary = ossl_asn1_get_value(self);
1272
+ if (!rb_obj_is_kind_of(ary, rb_cArray))
1273
+ ossl_raise(eASN1Error, "Constructive value must be an Array");
1274
+ /* Recursively descend until a primitive value is found.
1275
+ The overall value of the entire constructed encoding
1276
+ is of the type of the first primitive encoding to be
1277
+ found. */
1278
+ while (!found_prim){
1279
+ example = rb_ary_entry(ary, 0);
1280
+ if (rb_obj_is_kind_of(example, cASN1Primitive)){
1281
+ found_prim = 1;
1282
+ }
1283
+ else {
1284
+ /* example is another ASN1Constructive */
1285
+ if (!rb_obj_is_kind_of(example, cASN1Constructive)){
1286
+ ossl_raise(eASN1Error, "invalid constructed encoding");
1287
+ return Qnil; /* dummy */
1288
+ }
1289
+ ary = ossl_asn1_get_value(example);
1290
+ }
1291
+ }
1292
+ tag = ossl_asn1_default_tag(example);
1293
+ }
1294
+ }
1295
+ else {
1296
+ if (CLASS_OF(self) == cASN1Constructive)
1297
+ ossl_raise(eASN1Error, "Constructive shall only be used with infinite length");
1298
+ tag = ossl_asn1_default_tag(self);
1299
+ }
963
1300
  explicit = ossl_asn1_is_explicit(self);
964
1301
  value = join_der(ossl_asn1_get_value(self));
965
1302
 
966
- seq_len = ASN1_object_size(1, RSTRING_LEN(value), tag);
967
- length = ASN1_object_size(1, seq_len, tn);
1303
+ seq_len = ossl_asn1_object_size(constructed, RSTRING_LENINT(value), tag);
1304
+ length = ossl_asn1_object_size(constructed, seq_len, tn);
968
1305
  str = rb_str_new(0, length);
969
- p = RSTRING_PTR(str);
1306
+ p = (unsigned char *)RSTRING_PTR(str);
970
1307
  if(tc == V_ASN1_UNIVERSAL)
971
- ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
1308
+ ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
972
1309
  else{
973
1310
  if(explicit){
974
- ASN1_put_object(&p, 1, seq_len, tn, tc);
975
- ASN1_put_object(&p, 1, RSTRING_LEN(value), tag, V_ASN1_UNIVERSAL);
1311
+ ossl_asn1_put_object(&p, constructed, seq_len, tn, tc);
1312
+ ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL);
1313
+ }
1314
+ else{
1315
+ ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
976
1316
  }
977
- else ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
978
1317
  }
979
1318
  memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
980
1319
  p += RSTRING_LEN(value);
1320
+
1321
+ /* In this case we need an additional EOC (one for the explicit part and
1322
+ * one for the Constructive itself. The EOC for the Constructive is
1323
+ * supplied by the user, but that for the "explicit wrapper" must be
1324
+ * added here.
1325
+ */
1326
+ if (explicit && inf_length == Qtrue) {
1327
+ ASN1_put_eoc(&p);
1328
+ }
981
1329
  ossl_str_adjust(str, p);
982
1330
 
983
1331
  return str;
984
1332
  }
985
1333
 
1334
+ /*
1335
+ * call-seq:
1336
+ * asn1_ary.each { |asn1| block } => asn1_ary
1337
+ *
1338
+ * Calls <i>block</i> once for each element in +self+, passing that element
1339
+ * as parameter +asn1+. If no block is given, an enumerator is returned
1340
+ * instead.
1341
+ *
1342
+ * == Example
1343
+ * asn1_ary.each do |asn1|
1344
+ * puts asn1
1345
+ * end
1346
+ */
986
1347
  static VALUE
987
1348
  ossl_asn1cons_each(VALUE self)
988
1349
  {
@@ -1070,6 +1431,7 @@ OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime)
1070
1431
  OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime)
1071
1432
  OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence)
1072
1433
  OSSL_ASN1_IMPL_FACTORY_METHOD(Set)
1434
+ OSSL_ASN1_IMPL_FACTORY_METHOD(EndOfContent)
1073
1435
 
1074
1436
  void
1075
1437
  Init_ossl_asn1()
@@ -1077,8 +1439,8 @@ Init_ossl_asn1()
1077
1439
  VALUE ary;
1078
1440
  int i;
1079
1441
 
1080
- #if 0 /* let rdoc know about mOSSL */
1081
- mOSSL = rb_define_module("OpenSSL");
1442
+ #if 0
1443
+ mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
1082
1444
  #endif
1083
1445
 
1084
1446
  sUNIVERSAL = rb_intern("UNIVERSAL");
@@ -1088,12 +1450,155 @@ Init_ossl_asn1()
1088
1450
  sEXPLICIT = rb_intern("EXPLICIT");
1089
1451
  sIMPLICIT = rb_intern("IMPLICIT");
1090
1452
 
1453
+ sivVALUE = rb_intern("@value");
1454
+ sivTAG = rb_intern("@tag");
1455
+ sivTAGGING = rb_intern("@tagging");
1456
+ sivTAG_CLASS = rb_intern("@tag_class");
1457
+ sivINFINITE_LENGTH = rb_intern("@infinite_length");
1458
+ sivUNUSED_BITS = rb_intern("@unused_bits");
1459
+
1460
+ /*
1461
+ * Document-module: OpenSSL::ASN1
1462
+ *
1463
+ * Abstract Syntax Notation One (or ASN.1) is a notation syntax to
1464
+ * describe data structures and is defined in ITU-T X.680. ASN.1 itself
1465
+ * does not mandate any encoding or parsing rules, but usually ASN.1 data
1466
+ * structures are encoded using the Distinguished Encoding Rules (DER) or
1467
+ * less often the Basic Encoding Rules (BER) described in ITU-T X.690. DER
1468
+ * and BER encodings are binary Tag-Length-Value (TLV) encodings that are
1469
+ * quite concise compared to other popular data description formats such
1470
+ * as XML, JSON etc.
1471
+ * ASN.1 data structures are very common in cryptographic applications,
1472
+ * e.g. X.509 public key certificates or certificate revocation lists
1473
+ * (CRLs) are all defined in ASN.1 and DER-encoded. ASN.1, DER and BER are
1474
+ * the building blocks of applied cryptography.
1475
+ * The ASN1 module provides the necessary classes that allow generation
1476
+ * of ASN.1 data structures and the methods to encode them using a DER
1477
+ * encoding. The decode method allows parsing arbitrary BER-/DER-encoded
1478
+ * data to a Ruby object that can then be modified and re-encoded at will.
1479
+ *
1480
+ * == ASN.1 class hierarchy
1481
+ *
1482
+ * The base class representing ASN.1 structures is ASN1Data. ASN1Data offers
1483
+ * attributes to read and set the +tag+, the +tag_class+ and finally the
1484
+ * +value+ of a particular ASN.1 item. Upon parsing, any tagged values
1485
+ * (implicit or explicit) will be represented by ASN1Data instances because
1486
+ * their "real type" can only be determined using out-of-band information
1487
+ * from the ASN.1 type declaration. Since this information is normally
1488
+ * known when encoding a type, all sub-classes of ASN1Data offer an
1489
+ * additional attribute +tagging+ that allows to encode a value implicitly
1490
+ * (+:IMPLICIT+) or explicitly (+:EXPLICIT+).
1491
+ *
1492
+ * === Constructive
1493
+ *
1494
+ * Constructive is, as its name implies, the base class for all
1495
+ * constructed encodings, i.e. those that consist of several values,
1496
+ * opposed to "primitive" encodings with just one single value.
1497
+ * Primitive values that are encoded with "infinite length" are typically
1498
+ * constructed (their values come in multiple chunks) and are therefore
1499
+ * represented by instances of Constructive. The value of an Constructive
1500
+ * is always an Array.
1501
+ *
1502
+ * ==== ASN1::Set and ASN1::Sequence
1503
+ *
1504
+ * The most common constructive encodings are SETs and SEQUENCEs, which is
1505
+ * why there are two sub-classes of Constructive representing each of
1506
+ * them.
1507
+ *
1508
+ * === Primitive
1509
+ *
1510
+ * This is the super class of all primitive values. Primitive
1511
+ * itself is not used when parsing ASN.1 data, all values are either
1512
+ * instances of a corresponding sub-class of Primitive or they are
1513
+ * instances of ASN1Data if the value was tagged implicitly or explicitly.
1514
+ * Please cf. Primitive documentation for details on sub-classes and
1515
+ * their respective mappings of ASN.1 data types to Ruby objects.
1516
+ *
1517
+ * == Possible values for +tagging+
1518
+ *
1519
+ * When constructing an ASN1Data object the ASN.1 type definition may
1520
+ * require certain elements to be either implicitly or explicitly tagged.
1521
+ * This can be achieved by setting the +tagging+ attribute manually for
1522
+ * sub-classes of ASN1Data. Use the symbol +:IMPLICIT+ for implicit
1523
+ * tagging and +:EXPLICIT+ if the element requires explicit tagging.
1524
+ *
1525
+ * == Possible values for +tag_class+
1526
+ *
1527
+ * It is possible to create arbitrary ASN1Data objects that also support
1528
+ * a PRIVATE or APPLICATION tag class. Possible values for the +tag_class+
1529
+ * attribute are:
1530
+ * * +:UNIVERSAL+ (the default for untagged values)
1531
+ * * +:CONTEXT_SPECIFIC+ (the default for tagged values)
1532
+ * * +:APPLICATION+
1533
+ * * +:PRIVATE+
1534
+ *
1535
+ * == Tag constants
1536
+ *
1537
+ * There is a constant defined for each universal tag:
1538
+ * * OpenSSL::ASN1::EOC (0)
1539
+ * * OpenSSL::ASN1::BOOLEAN (1)
1540
+ * * OpenSSL::ASN1::INTEGER (2)
1541
+ * * OpenSSL::ASN1::BIT_STRING (3)
1542
+ * * OpenSSL::ASN1::OCTET_STRING (4)
1543
+ * * OpenSSL::ASN1::NULL (5)
1544
+ * * OpenSSL::ASN1::OBJECT (6)
1545
+ * * OpenSSL::ASN1::ENUMERATED (10)
1546
+ * * OpenSSL::ASN1::UTF8STRING (12)
1547
+ * * OpenSSL::ASN1::SEQUENCE (16)
1548
+ * * OpenSSL::ASN1::SET (17)
1549
+ * * OpenSSL::ASN1::NUMERICSTRING (18)
1550
+ * * OpenSSL::ASN1::PRINTABLESTRING (19)
1551
+ * * OpenSSL::ASN1::T61STRING (20)
1552
+ * * OpenSSL::ASN1::VIDEOTEXSTRING (21)
1553
+ * * OpenSSL::ASN1::IA5STRING (22)
1554
+ * * OpenSSL::ASN1::UTCTIME (23)
1555
+ * * OpenSSL::ASN1::GENERALIZEDTIME (24)
1556
+ * * OpenSSL::ASN1::GRAPHICSTRING (25)
1557
+ * * OpenSSL::ASN1::ISO64STRING (26)
1558
+ * * OpenSSL::ASN1::GENERALSTRING (27)
1559
+ * * OpenSSL::ASN1::UNIVERSALSTRING (28)
1560
+ * * OpenSSL::ASN1::BMPSTRING (30)
1561
+ *
1562
+ * == UNIVERSAL_TAG_NAME constant
1563
+ *
1564
+ * An Array that stores the name of a given tag number. These names are
1565
+ * the same as the name of the tag constant that is additionally defined,
1566
+ * e.g. UNIVERSAL_TAG_NAME[2] = "INTEGER" and OpenSSL::ASN1::INTEGER = 2.
1567
+ *
1568
+ * == Example usage
1569
+ *
1570
+ * === Decoding and viewing a DER-encoded file
1571
+ * require 'openssl'
1572
+ * require 'pp'
1573
+ * der = File.binread('data.der')
1574
+ * asn1 = OpenSSL::ASN1.decode(der)
1575
+ * pp der
1576
+ *
1577
+ * === Creating an ASN.1 structure and DER-encoding it
1578
+ * require 'openssl'
1579
+ * version = OpenSSL::ASN1::Integer.new(1)
1580
+ * # Explicitly 0-tagged implies context-specific tag class
1581
+ * serial = OpenSSL::ASN1::Integer.new(12345, 0, :EXPLICIT, :CONTEXT_SPECIFIC)
1582
+ * name = OpenSSL::ASN1::PrintableString.new('Data 1')
1583
+ * sequence = OpenSSL::ASN1::Sequence.new( [ version, serial, name ] )
1584
+ * der = sequence.to_der
1585
+ */
1091
1586
  mASN1 = rb_define_module_under(mOSSL, "ASN1");
1587
+
1588
+ /* Document-class: OpenSSL::ASN1::ASN1Error
1589
+ *
1590
+ * Generic error class for all errors raised in ASN1 and any of the
1591
+ * classes defined in it.
1592
+ */
1092
1593
  eASN1Error = rb_define_class_under(mASN1, "ASN1Error", eOSSLError);
1093
1594
  rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1);
1094
1595
  rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1);
1095
1596
  rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1);
1096
1597
  ary = rb_ary_new();
1598
+
1599
+ /*
1600
+ * Array storing tag names at the tag's index.
1601
+ */
1097
1602
  rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
1098
1603
  for(i = 0; i < ossl_asn1_info_size; i++){
1099
1604
  if(ossl_asn1_info[i].name[0] == '[') continue;
@@ -1101,20 +1606,272 @@ Init_ossl_asn1()
1101
1606
  rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name));
1102
1607
  }
1103
1608
 
1609
+ /* Document-class: OpenSSL::ASN1::ASN1Data
1610
+ *
1611
+ * The top-level class representing any ASN.1 object. When parsed by
1612
+ * ASN1.decode, tagged values are always represented by an instance
1613
+ * of ASN1Data.
1614
+ *
1615
+ * == The role of ASN1Data for parsing tagged values
1616
+ *
1617
+ * When encoding an ASN.1 type it is inherently clear what original
1618
+ * type (e.g. INTEGER, OCTET STRING etc.) this value has, regardless
1619
+ * of its tagging.
1620
+ * But opposed to the time an ASN.1 type is to be encoded, when parsing
1621
+ * them it is not possible to deduce the "real type" of tagged
1622
+ * values. This is why tagged values are generally parsed into ASN1Data
1623
+ * instances, but with a different outcome for implicit and explicit
1624
+ * tagging.
1625
+ *
1626
+ * === Example of a parsed implicitly tagged value
1627
+ *
1628
+ * An implicitly 1-tagged INTEGER value will be parsed as an
1629
+ * ASN1Data with
1630
+ * * +tag+ equal to 1
1631
+ * * +tag_class+ equal to +:CONTEXT_SPECIFIC+
1632
+ * * +value+ equal to a +String+ that carries the raw encoding
1633
+ * of the INTEGER.
1634
+ * This implies that a subsequent decoding step is required to
1635
+ * completely decode implicitly tagged values.
1636
+ *
1637
+ * === Example of a parsed explicitly tagged value
1638
+ *
1639
+ * An explicitly 1-tagged INTEGER value will be parsed as an
1640
+ * ASN1Data with
1641
+ * * +tag+ equal to 1
1642
+ * * +tag_class+ equal to +:CONTEXT_SPECIFIC+
1643
+ * * +value+ equal to an +Array+ with one single element, an
1644
+ * instance of OpenSSL::ASN1::Integer, i.e. the inner element
1645
+ * is the non-tagged primitive value, and the tagging is represented
1646
+ * in the outer ASN1Data
1647
+ *
1648
+ * == Example - Decoding an implicitly tagged INTEGER
1649
+ * int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT) # implicit 0-tagged
1650
+ * seq = OpenSSL::ASN1::Sequence.new( [int] )
1651
+ * der = seq.to_der
1652
+ * asn1 = OpenSSL::ASN1.decode(der)
1653
+ * # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
1654
+ * # @infinite_length=false,
1655
+ * # @tag=16,
1656
+ * # @tag_class=:UNIVERSAL,
1657
+ * # @tagging=nil,
1658
+ * # @value=
1659
+ * # [#<OpenSSL::ASN1::ASN1Data:0x87326f4
1660
+ * # @infinite_length=false,
1661
+ * # @tag=0,
1662
+ * # @tag_class=:CONTEXT_SPECIFIC,
1663
+ * # @value="\x01">]>
1664
+ * raw_int = asn1.value[0]
1665
+ * # manually rewrite tag and tag class to make it an UNIVERSAL value
1666
+ * raw_int.tag = OpenSSL::ASN1::INTEGER
1667
+ * raw_int.tag_class = :UNIVERSAL
1668
+ * int2 = OpenSSL::ASN1.decode(raw_int)
1669
+ * puts int2.value # => 1
1670
+ *
1671
+ * == Example - Decoding an explicitly tagged INTEGER
1672
+ * int = OpenSSL::ASN1::Integer.new(1, 0, :EXPLICIT) # explicit 0-tagged
1673
+ * seq = OpenSSL::ASN1::Sequence.new( [int] )
1674
+ * der = seq.to_der
1675
+ * asn1 = OpenSSL::ASN1.decode(der)
1676
+ * # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
1677
+ * # @infinite_length=false,
1678
+ * # @tag=16,
1679
+ * # @tag_class=:UNIVERSAL,
1680
+ * # @tagging=nil,
1681
+ * # @value=
1682
+ * # [#<OpenSSL::ASN1::ASN1Data:0x87326f4
1683
+ * # @infinite_length=false,
1684
+ * # @tag=0,
1685
+ * # @tag_class=:CONTEXT_SPECIFIC,
1686
+ * # @value=
1687
+ * # [#<OpenSSL::ASN1::Integer:0x85bf308
1688
+ * # @infinite_length=false,
1689
+ * # @tag=2,
1690
+ * # @tag_class=:UNIVERSAL
1691
+ * # @tagging=nil,
1692
+ * # @value=1>]>]>
1693
+ * int2 = asn1.value[0].value[0]
1694
+ * puts int2.value # => 1
1695
+ */
1104
1696
  cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
1697
+ /*
1698
+ * Carries the value of a ASN.1 type.
1699
+ * Please confer Constructive and Primitive for the mappings between
1700
+ * ASN.1 data types and Ruby classes.
1701
+ */
1105
1702
  rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
1703
+ /*
1704
+ * A +Number+ representing the tag number of this ASN1Data. Never +nil+.
1705
+ */
1106
1706
  rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
1707
+ /*
1708
+ * A +Symbol+ representing the tag class of this ASN1Data. Never +nil+.
1709
+ * See ASN1Data for possible values.
1710
+ */
1107
1711
  rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
1712
+ /*
1713
+ * Never +nil+. A +Boolean+ indicating whether the encoding was infinite
1714
+ * length (in the case of parsing) or whether an infinite length encoding
1715
+ * shall be used (in the encoding case).
1716
+ * In DER, every value has a finite length associated with it. But in
1717
+ * scenarios where large amounts of data need to be transferred it
1718
+ * might be desirable to have some kind of streaming support available.
1719
+ * For example, huge OCTET STRINGs are preferably sent in smaller-sized
1720
+ * chunks, each at a time.
1721
+ * This is possible in BER by setting the length bytes of an encoding
1722
+ * to zero and by this indicating that the following value will be
1723
+ * sent in chunks. Infinite length encodings are always constructed.
1724
+ * The end of such a stream of chunks is indicated by sending a EOC
1725
+ * (End of Content) tag. SETs and SEQUENCEs may use an infinite length
1726
+ * encoding, but also primitive types such as e.g. OCTET STRINGS or
1727
+ * BIT STRINGS may leverage this functionality (cf. ITU-T X.690).
1728
+ */
1729
+ rb_attr(cASN1Data, rb_intern("infinite_length"), 1, 1, 0);
1108
1730
  rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
1109
1731
  rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
1110
1732
 
1733
+ /* Document-class: OpenSSL::ASN1::Primitive
1734
+ *
1735
+ * The parent class for all primitive encodings. Attributes are the same as
1736
+ * for ASN1Data, with the addition of +tagging+.
1737
+ * Primitive values can never be infinite length encodings, thus it is not
1738
+ * possible to set the +infinite_length+ attribute for Primitive and its
1739
+ * sub-classes.
1740
+ *
1741
+ * == Primitive sub-classes and their mapping to Ruby classes
1742
+ * * OpenSSL::ASN1::EndOfContent <=> +value+ is always +nil+
1743
+ * * OpenSSL::ASN1::Boolean <=> +value+ is a +Boolean+
1744
+ * * OpenSSL::ASN1::Integer <=> +value+ is a +Number+
1745
+ * * OpenSSL::ASN1::BitString <=> +value+ is a +String+
1746
+ * * OpenSSL::ASN1::OctetString <=> +value+ is a +String+
1747
+ * * OpenSSL::ASN1::Null <=> +value+ is always +nil+
1748
+ * * OpenSSL::ASN1::Object <=> +value+ is a +String+
1749
+ * * OpenSSL::ASN1::Enumerated <=> +value+ is a +Number+
1750
+ * * OpenSSL::ASN1::UTF8String <=> +value+ is a +String+
1751
+ * * OpenSSL::ASN1::NumericString <=> +value+ is a +String+
1752
+ * * OpenSSL::ASN1::PrintableString <=> +value+ is a +String+
1753
+ * * OpenSSL::ASN1::T61String <=> +value+ is a +String+
1754
+ * * OpenSSL::ASN1::VideotexString <=> +value+ is a +String+
1755
+ * * OpenSSL::ASN1::IA5String <=> +value+ is a +String+
1756
+ * * OpenSSL::ASN1::UTCTime <=> +value+ is a +Time+
1757
+ * * OpenSSL::ASN1::GeneralizedTime <=> +value+ is a +Time+
1758
+ * * OpenSSL::ASN1::GraphicString <=> +value+ is a +String+
1759
+ * * OpenSSL::ASN1::ISO64String <=> +value+ is a +String+
1760
+ * * OpenSSL::ASN1::GeneralString <=> +value+ is a +String+
1761
+ * * OpenSSL::ASN1::UniversalString <=> +value+ is a +String+
1762
+ * * OpenSSL::ASN1::BMPString <=> +value+ is a +String+
1763
+ *
1764
+ * == OpenSSL::ASN1::BitString
1765
+ *
1766
+ * === Additional attributes
1767
+ * +unused_bits+: if the underlying BIT STRING's
1768
+ * length is a multiple of 8 then +unused_bits+ is 0. Otherwise
1769
+ * +unused_bits+ indicates the number of bits that are to be ignored in
1770
+ * the final octet of the +BitString+'s +value+.
1771
+ *
1772
+ * == OpenSSL::ASN1::ObjectId
1773
+ *
1774
+ * === Additional attributes
1775
+ * * +sn+: the short name as defined in <openssl/objects.h>.
1776
+ * * +ln+: the long name as defined in <openssl/objects.h>.
1777
+ * * +oid+: the object identifier as a +String+, e.g. "1.2.3.4.5"
1778
+ * * +short_name+: alias for +sn+.
1779
+ * * +long_name+: alias for +ln+.
1780
+ *
1781
+ * == Examples
1782
+ * With the Exception of OpenSSL::ASN1::EndOfContent, each Primitive class
1783
+ * constructor takes at least one parameter, the +value+.
1784
+ *
1785
+ * === Creating EndOfContent
1786
+ * eoc = OpenSSL::ASN1::EndOfContent.new
1787
+ *
1788
+ * === Creating any other Primitive
1789
+ * prim = <class>.new(value) # <class> being one of the sub-classes except EndOfContent
1790
+ * prim_zero_tagged_implicit = <class>.new(value, 0, :IMPLICIT)
1791
+ * prim_zero_tagged_explicit = <class>.new(value, 0, :EXPLICIT)
1792
+ */
1111
1793
  cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data);
1794
+ /*
1795
+ * May be used as a hint for encoding a value either implicitly or
1796
+ * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
1797
+ * +tagging+ is not set when a ASN.1 structure is parsed using
1798
+ * OpenSSL::ASN1.decode.
1799
+ */
1112
1800
  rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
1801
+ rb_undef_method(cASN1Primitive, "infinite_length=");
1113
1802
  rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
1114
1803
  rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);
1115
1804
 
1805
+ /* Document-class: OpenSSL::ASN1::Constructive
1806
+ *
1807
+ * The parent class for all constructed encodings. The +value+ attribute
1808
+ * of a Constructive is always an +Array+. Attributes are the same as
1809
+ * for ASN1Data, with the addition of +tagging+.
1810
+ *
1811
+ * == SET and SEQUENCE
1812
+ *
1813
+ * Most constructed encodings come in the form of a SET or a SEQUENCE.
1814
+ * These encodings are represented by one of the two sub-classes of
1815
+ * Constructive:
1816
+ * * OpenSSL::ASN1::Set
1817
+ * * OpenSSL::ASN1::Sequence
1818
+ * Please note that tagged sequences and sets are still parsed as
1819
+ * instances of ASN1Data. Find further details on tagged values
1820
+ * there.
1821
+ *
1822
+ * === Example - constructing a SEQUENCE
1823
+ * int = OpenSSL::ASN1::Integer.new(1)
1824
+ * str = OpenSSL::ASN1::PrintableString.new('abc')
1825
+ * sequence = OpenSSL::ASN1::Sequence.new( [ int, str ] )
1826
+ *
1827
+ * === Example - constructing a SET
1828
+ * int = OpenSSL::ASN1::Integer.new(1)
1829
+ * str = OpenSSL::ASN1::PrintableString.new('abc')
1830
+ * set = OpenSSL::ASN1::Set.new( [ int, str ] )
1831
+ *
1832
+ * == Infinite length primitive values
1833
+ *
1834
+ * The only case where Constructive is used directly is for infinite
1835
+ * length encodings of primitive values. These encodings are always
1836
+ * constructed, with the contents of the +value+ +Array+ being either
1837
+ * UNIVERSAL non-infinite length partial encodings of the actual value
1838
+ * or again constructive encodings with infinite length (i.e. infinite
1839
+ * length primitive encodings may be constructed recursively with another
1840
+ * infinite length value within an already infinite length value). Each
1841
+ * partial encoding must be of the same UNIVERSAL type as the overall
1842
+ * encoding. The value of the overall encoding consists of the
1843
+ * concatenation of each partial encoding taken in sequence. The +value+
1844
+ * array of the outer infinite length value must end with a
1845
+ * OpenSSL::ASN1::EndOfContent instance.
1846
+ *
1847
+ * Please note that it is not possible to encode Constructive without
1848
+ * the +infinite_length+ attribute being set to +true+, use
1849
+ * OpenSSL::ASN1::Sequence or OpenSSL::ASN1::Set in these cases instead.
1850
+ *
1851
+ * === Example - Infinite length OCTET STRING
1852
+ * partial1 = OpenSSL::ASN1::OctetString.new("\x01")
1853
+ * partial2 = OpenSSL::ASN1::OctetString.new("\x02")
1854
+ * inf_octets = OpenSSL::ASN1::Constructive.new( [ partial1,
1855
+ * partial2,
1856
+ * OpenSSL::ASN1::EndOfContent.new ],
1857
+ * OpenSSL::ASN1::OCTET_STRING,
1858
+ * nil,
1859
+ * :UNIVERSAL )
1860
+ * # The real value of inf_octets is "\x01\x02", i.e. the concatenation
1861
+ * # of partial1 and partial2
1862
+ * inf_octets.infinite_length = true
1863
+ * der = inf_octets.to_der
1864
+ * asn1 = OpenSSL::ASN1.decode(der)
1865
+ * puts asn1.infinite_length # => true
1866
+ */
1116
1867
  cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data);
1117
1868
  rb_include_module(cASN1Constructive, rb_mEnumerable);
1869
+ /*
1870
+ * May be used as a hint for encoding a value either implicitly or
1871
+ * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
1872
+ * +tagging+ is not set when a ASN.1 structure is parsed using
1873
+ * OpenSSL::ASN1.decode.
1874
+ */
1118
1875
  rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
1119
1876
  rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
1120
1877
  rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0);
@@ -1150,6 +1907,12 @@ do{\
1150
1907
  OSSL_ASN1_DEFINE_CLASS(Sequence, Constructive);
1151
1908
  OSSL_ASN1_DEFINE_CLASS(Set, Constructive);
1152
1909
 
1910
+ OSSL_ASN1_DEFINE_CLASS(EndOfContent, Data);
1911
+
1912
+
1913
+ #if 0
1914
+ cASN1ObjectId = rb_define_class_under(mASN1, "ObjectId", cASN1Primitive); /* let rdoc know */
1915
+ #endif
1153
1916
  rb_define_singleton_method(cASN1ObjectId, "register", ossl_asn1obj_s_register, 3);
1154
1917
  rb_define_method(cASN1ObjectId, "sn", ossl_asn1obj_get_sn, 0);
1155
1918
  rb_define_method(cASN1ObjectId, "ln", ossl_asn1obj_get_ln, 0);
@@ -1157,4 +1920,32 @@ do{\
1157
1920
  rb_define_alias(cASN1ObjectId, "short_name", "sn");
1158
1921
  rb_define_alias(cASN1ObjectId, "long_name", "ln");
1159
1922
  rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
1923
+
1924
+ rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
1925
+
1926
+ class_tag_map = rb_hash_new();
1927
+ rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC));
1928
+ rb_hash_aset(class_tag_map, cASN1Boolean, INT2NUM(V_ASN1_BOOLEAN));
1929
+ rb_hash_aset(class_tag_map, cASN1Integer, INT2NUM(V_ASN1_INTEGER));
1930
+ rb_hash_aset(class_tag_map, cASN1BitString, INT2NUM(V_ASN1_BIT_STRING));
1931
+ rb_hash_aset(class_tag_map, cASN1OctetString, INT2NUM(V_ASN1_OCTET_STRING));
1932
+ rb_hash_aset(class_tag_map, cASN1Null, INT2NUM(V_ASN1_NULL));
1933
+ rb_hash_aset(class_tag_map, cASN1ObjectId, INT2NUM(V_ASN1_OBJECT));
1934
+ rb_hash_aset(class_tag_map, cASN1Enumerated, INT2NUM(V_ASN1_ENUMERATED));
1935
+ rb_hash_aset(class_tag_map, cASN1UTF8String, INT2NUM(V_ASN1_UTF8STRING));
1936
+ rb_hash_aset(class_tag_map, cASN1Sequence, INT2NUM(V_ASN1_SEQUENCE));
1937
+ rb_hash_aset(class_tag_map, cASN1Set, INT2NUM(V_ASN1_SET));
1938
+ rb_hash_aset(class_tag_map, cASN1NumericString, INT2NUM(V_ASN1_NUMERICSTRING));
1939
+ rb_hash_aset(class_tag_map, cASN1PrintableString, INT2NUM(V_ASN1_PRINTABLESTRING));
1940
+ rb_hash_aset(class_tag_map, cASN1T61String, INT2NUM(V_ASN1_T61STRING));
1941
+ rb_hash_aset(class_tag_map, cASN1VideotexString, INT2NUM(V_ASN1_VIDEOTEXSTRING));
1942
+ rb_hash_aset(class_tag_map, cASN1IA5String, INT2NUM(V_ASN1_IA5STRING));
1943
+ rb_hash_aset(class_tag_map, cASN1UTCTime, INT2NUM(V_ASN1_UTCTIME));
1944
+ rb_hash_aset(class_tag_map, cASN1GeneralizedTime, INT2NUM(V_ASN1_GENERALIZEDTIME));
1945
+ rb_hash_aset(class_tag_map, cASN1GraphicString, INT2NUM(V_ASN1_GRAPHICSTRING));
1946
+ rb_hash_aset(class_tag_map, cASN1ISO64String, INT2NUM(V_ASN1_ISO64STRING));
1947
+ rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
1948
+ rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
1949
+ rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
1950
+ rb_global_variable(&class_tag_map);
1160
1951
  }