rubysl-openssl 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }