rubysl-openssl 0.0.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +0 -1
  3. data/.travis.yml +7 -0
  4. data/README.md +2 -2
  5. data/Rakefile +0 -1
  6. data/ext/rubysl/openssl/extconf.h +50 -0
  7. data/ext/rubysl/openssl/extconf.rb +144 -0
  8. data/ext/rubysl/openssl/openssl_missing.c +343 -0
  9. data/ext/rubysl/openssl/openssl_missing.h +191 -0
  10. data/ext/rubysl/openssl/ossl.c +552 -0
  11. data/ext/rubysl/openssl/ossl.h +233 -0
  12. data/ext/rubysl/openssl/ossl_asn1.c +1160 -0
  13. data/ext/rubysl/openssl/ossl_asn1.h +59 -0
  14. data/ext/rubysl/openssl/ossl_bio.c +86 -0
  15. data/ext/rubysl/openssl/ossl_bio.h +21 -0
  16. data/ext/rubysl/openssl/ossl_bn.c +852 -0
  17. data/ext/rubysl/openssl/ossl_bn.h +25 -0
  18. data/ext/rubysl/openssl/ossl_cipher.c +569 -0
  19. data/ext/rubysl/openssl/ossl_cipher.h +22 -0
  20. data/ext/rubysl/openssl/ossl_config.c +75 -0
  21. data/ext/rubysl/openssl/ossl_config.h +22 -0
  22. data/ext/rubysl/openssl/ossl_digest.c +259 -0
  23. data/ext/rubysl/openssl/ossl_digest.h +22 -0
  24. data/ext/rubysl/openssl/ossl_engine.c +411 -0
  25. data/ext/rubysl/openssl/ossl_engine.h +20 -0
  26. data/ext/rubysl/openssl/ossl_hmac.c +268 -0
  27. data/ext/rubysl/openssl/ossl_hmac.h +19 -0
  28. data/ext/rubysl/openssl/ossl_ns_spki.c +257 -0
  29. data/ext/rubysl/openssl/ossl_ns_spki.h +21 -0
  30. data/ext/rubysl/openssl/ossl_ocsp.c +769 -0
  31. data/ext/rubysl/openssl/ossl_ocsp.h +24 -0
  32. data/ext/rubysl/openssl/ossl_pkcs12.c +210 -0
  33. data/ext/rubysl/openssl/ossl_pkcs12.h +15 -0
  34. data/ext/rubysl/openssl/ossl_pkcs5.c +99 -0
  35. data/ext/rubysl/openssl/ossl_pkcs5.h +6 -0
  36. data/ext/rubysl/openssl/ossl_pkcs7.c +1039 -0
  37. data/ext/rubysl/openssl/ossl_pkcs7.h +22 -0
  38. data/ext/rubysl/openssl/ossl_pkey.c +240 -0
  39. data/ext/rubysl/openssl/ossl_pkey.h +141 -0
  40. data/ext/rubysl/openssl/ossl_pkey_dh.c +532 -0
  41. data/ext/rubysl/openssl/ossl_pkey_dsa.c +484 -0
  42. data/ext/rubysl/openssl/ossl_pkey_ec.c +1593 -0
  43. data/ext/rubysl/openssl/ossl_pkey_rsa.c +593 -0
  44. data/ext/rubysl/openssl/ossl_rand.c +202 -0
  45. data/ext/rubysl/openssl/ossl_rand.h +20 -0
  46. data/ext/rubysl/openssl/ossl_ssl.c +1484 -0
  47. data/ext/rubysl/openssl/ossl_ssl.h +36 -0
  48. data/ext/rubysl/openssl/ossl_ssl_session.c +307 -0
  49. data/ext/rubysl/openssl/ossl_version.h +16 -0
  50. data/ext/rubysl/openssl/ossl_x509.c +104 -0
  51. data/ext/rubysl/openssl/ossl_x509.h +114 -0
  52. data/ext/rubysl/openssl/ossl_x509attr.c +274 -0
  53. data/ext/rubysl/openssl/ossl_x509cert.c +764 -0
  54. data/ext/rubysl/openssl/ossl_x509crl.c +535 -0
  55. data/ext/rubysl/openssl/ossl_x509ext.c +458 -0
  56. data/ext/rubysl/openssl/ossl_x509name.c +399 -0
  57. data/ext/rubysl/openssl/ossl_x509req.c +466 -0
  58. data/ext/rubysl/openssl/ossl_x509revoked.c +229 -0
  59. data/ext/rubysl/openssl/ossl_x509store.c +625 -0
  60. data/ext/rubysl/openssl/ruby_missing.h +41 -0
  61. data/lib/openssl.rb +1 -0
  62. data/lib/openssl/bn.rb +35 -0
  63. data/lib/openssl/buffering.rb +241 -0
  64. data/lib/openssl/cipher.rb +65 -0
  65. data/lib/openssl/config.rb +316 -0
  66. data/lib/openssl/digest.rb +61 -0
  67. data/lib/openssl/net/ftptls.rb +53 -0
  68. data/lib/openssl/net/telnets.rb +251 -0
  69. data/lib/openssl/pkcs7.rb +25 -0
  70. data/lib/openssl/ssl-internal.rb +187 -0
  71. data/lib/openssl/ssl.rb +1 -0
  72. data/lib/openssl/x509-internal.rb +153 -0
  73. data/lib/openssl/x509.rb +1 -0
  74. data/lib/rubysl/openssl.rb +28 -0
  75. data/lib/rubysl/openssl/version.rb +5 -0
  76. data/rubysl-openssl.gemspec +19 -18
  77. data/spec/cipher_spec.rb +16 -0
  78. data/spec/config/freeze_spec.rb +17 -0
  79. data/spec/hmac/digest_spec.rb +15 -0
  80. data/spec/hmac/hexdigest_spec.rb +15 -0
  81. data/spec/random/pseudo_bytes_spec.rb +5 -0
  82. data/spec/random/random_bytes_spec.rb +5 -0
  83. data/spec/random/shared/random_bytes.rb +28 -0
  84. data/spec/shared/constants.rb +11 -0
  85. data/spec/x509/name/parse_spec.rb +47 -0
  86. metadata +153 -89
  87. data/lib/rubysl-openssl.rb +0 -7
  88. data/lib/rubysl-openssl/version.rb +0 -5
@@ -0,0 +1,233 @@
1
+ /*
2
+ * $Id: ossl.h 28367 2010-06-21 09:18:59Z shyouhei $
3
+ * 'OpenSSL for Ruby' project
4
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
+ * All rights reserved.
6
+ */
7
+ /*
8
+ * This program is licenced under the same licence as Ruby.
9
+ * (See the file 'LICENCE'.)
10
+ */
11
+ #if !defined(_OSSL_H_)
12
+ #define _OSSL_H_
13
+
14
+ #include RUBY_EXTCONF_H
15
+
16
+ #if defined(__cplusplus)
17
+ extern "C" {
18
+ #endif
19
+
20
+ #if 0
21
+ mOSSL = rb_define_module("OpenSSL");
22
+ mX509 = rb_define_module_under(mOSSL, "X509");
23
+ #endif
24
+
25
+ /*
26
+ * OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
27
+ */
28
+ #if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/
29
+ # undef RFILE
30
+ #endif
31
+ #include <ruby.h>
32
+ #include <rubyio.h>
33
+
34
+ /*
35
+ * Check the OpenSSL version
36
+ * The only supported are:
37
+ * OpenSSL >= 0.9.7
38
+ */
39
+ #include <openssl/opensslv.h>
40
+
41
+ #ifdef HAVE_ASSERT_H
42
+ # include <assert.h>
43
+ #else
44
+ # define assert(condition)
45
+ #endif
46
+
47
+ #if defined(_WIN32)
48
+ # define OSSL_NO_CONF_API 1
49
+ # ifdef USE_WINSOCK2
50
+ # include <winsock2.h>
51
+ # else
52
+ # include <winsock.h>
53
+ # endif
54
+ #endif
55
+ #include <errno.h>
56
+ #include <openssl/err.h>
57
+ #include <openssl/asn1_mac.h>
58
+ #include <openssl/x509v3.h>
59
+ #include <openssl/ssl.h>
60
+ #include <openssl/pkcs12.h>
61
+ #include <openssl/pkcs7.h>
62
+ #include <openssl/hmac.h>
63
+ #include <openssl/rand.h>
64
+ #include <openssl/conf.h>
65
+ #include <openssl/conf_api.h>
66
+ #undef X509_NAME
67
+ #undef PKCS7_SIGNER_INFO
68
+ #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ST_ENGINE)
69
+ # define OSSL_ENGINE_ENABLED
70
+ # include <openssl/engine.h>
71
+ #endif
72
+ #if defined(HAVE_OPENSSL_OCSP_H)
73
+ # define OSSL_OCSP_ENABLED
74
+ # include <openssl/ocsp.h>
75
+ #endif
76
+
77
+ /*
78
+ * Common Module
79
+ */
80
+ extern VALUE mOSSL;
81
+
82
+ /*
83
+ * Common Error Class
84
+ */
85
+ extern VALUE eOSSLError;
86
+
87
+ /*
88
+ * CheckTypes
89
+ */
90
+ #define OSSL_Check_Kind(obj, klass) do {\
91
+ if (!rb_obj_is_kind_of(obj, klass)) {\
92
+ ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected kind of %s)",\
93
+ rb_obj_classname(obj), rb_class2name(klass));\
94
+ }\
95
+ } while (0)
96
+
97
+ #define OSSL_Check_Instance(obj, klass) do {\
98
+ if (!rb_obj_is_instance_of(obj, klass)) {\
99
+ ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected instance of %s)",\
100
+ rb_obj_classname(obj), rb_class2name(klass));\
101
+ }\
102
+ } while (0)
103
+
104
+ #define OSSL_Check_Same_Class(obj1, obj2) do {\
105
+ if (!rb_obj_is_instance_of(obj1, rb_obj_class(obj2))) {\
106
+ ossl_raise(rb_eTypeError, "wrong argument type");\
107
+ }\
108
+ } while (0)
109
+
110
+ /*
111
+ * Compatibility
112
+ */
113
+ #if OPENSSL_VERSION_NUMBER >= 0x10000000L
114
+ #define STACK _STACK
115
+ #endif
116
+
117
+ /*
118
+ * String to HEXString conversion
119
+ */
120
+ int string2hex(char *, int, char **, int *);
121
+
122
+ /*
123
+ * Data Conversion
124
+ */
125
+ STACK_OF(X509) *ossl_x509_ary2sk0(VALUE);
126
+ STACK_OF(X509) *ossl_x509_ary2sk(VALUE);
127
+ STACK_OF(X509) *ossl_protect_x509_ary2sk(VALUE,int*);
128
+ VALUE ossl_x509_sk2ary(STACK_OF(X509) *certs);
129
+ VALUE ossl_x509crl_sk2ary(STACK_OF(X509_CRL) *crl);
130
+ VALUE ossl_buf2str(char *buf, int len);
131
+ #define ossl_str_adjust(str, p) \
132
+ do{\
133
+ int len = RSTRING_LEN(str);\
134
+ int newlen = (p) - (unsigned char*)RSTRING_PTR(str);\
135
+ assert(newlen <= len);\
136
+ rb_str_set_len(str, newlen);\
137
+ }while(0)
138
+
139
+ /*
140
+ * our default PEM callback
141
+ */
142
+ int ossl_pem_passwd_cb(char *, int, int, void *);
143
+
144
+ /*
145
+ * ERRor messages
146
+ */
147
+ #define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error())
148
+ NORETURN(void ossl_raise(VALUE, const char *, ...));
149
+ VALUE ossl_exc_new(VALUE, const char *, ...);
150
+
151
+ /*
152
+ * Verify callback
153
+ */
154
+ extern int ossl_verify_cb_idx;
155
+
156
+ struct ossl_verify_cb_args {
157
+ VALUE proc;
158
+ VALUE preverify_ok;
159
+ VALUE store_ctx;
160
+ };
161
+
162
+ VALUE ossl_call_verify_cb_proc(struct ossl_verify_cb_args *);
163
+ int ossl_verify_cb(int, X509_STORE_CTX *);
164
+
165
+ /*
166
+ * String to DER String
167
+ */
168
+ extern ID ossl_s_to_der;
169
+ VALUE ossl_to_der(VALUE);
170
+ VALUE ossl_to_der_if_possible(VALUE);
171
+
172
+ /*
173
+ * Debug
174
+ */
175
+ extern VALUE dOSSL;
176
+
177
+ #if defined(HAVE_VA_ARGS_MACRO)
178
+ #define OSSL_Debug(...) do { \
179
+ if (dOSSL == Qtrue) { \
180
+ fprintf(stderr, "OSSL_DEBUG: "); \
181
+ fprintf(stderr, __VA_ARGS__); \
182
+ fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \
183
+ } \
184
+ } while (0)
185
+
186
+ #define OSSL_Warning(fmt, ...) do { \
187
+ OSSL_Debug(fmt, ##__VA_ARGS__); \
188
+ rb_warning(fmt, ##__VA_ARGS__); \
189
+ } while (0)
190
+
191
+ #define OSSL_Warn(fmt, ...) do { \
192
+ OSSL_Debug(fmt, ##__VA_ARGS__); \
193
+ rb_warn(fmt, ##__VA_ARGS__); \
194
+ } while (0)
195
+ #else
196
+ void ossl_debug(const char *, ...);
197
+ #define OSSL_Debug ossl_debug
198
+ #define OSSL_Warning rb_warning
199
+ #define OSSL_Warn rb_warn
200
+ #endif
201
+
202
+ /*
203
+ * Include all parts
204
+ */
205
+ #include "openssl_missing.h"
206
+ #include "ruby_missing.h"
207
+ #include "ossl_asn1.h"
208
+ #include "ossl_bio.h"
209
+ #include "ossl_bn.h"
210
+ #include "ossl_cipher.h"
211
+ #include "ossl_config.h"
212
+ #include "ossl_digest.h"
213
+ #include "ossl_hmac.h"
214
+ #include "ossl_ns_spki.h"
215
+ #include "ossl_ocsp.h"
216
+ #include "ossl_pkcs12.h"
217
+ #include "ossl_pkcs7.h"
218
+ #include "ossl_pkcs5.h"
219
+ #include "ossl_pkey.h"
220
+ #include "ossl_rand.h"
221
+ #include "ossl_ssl.h"
222
+ #include "ossl_version.h"
223
+ #include "ossl_x509.h"
224
+ #include "ossl_engine.h"
225
+
226
+ void Init_openssl(void);
227
+
228
+ #if defined(__cplusplus)
229
+ }
230
+ #endif
231
+
232
+ #endif /* _OSSL_H_ */
233
+
@@ -0,0 +1,1160 @@
1
+ /*
2
+ * $Id$
3
+ * 'OpenSSL for Ruby' team members
4
+ * Copyright (C) 2003
5
+ * All rights reserved.
6
+ */
7
+ /*
8
+ * This program is licenced under the same licence as Ruby.
9
+ * (See the file 'LICENCE'.)
10
+ */
11
+ #include "ossl.h"
12
+
13
+ #include <sys/time.h>
14
+
15
+ /*
16
+ * DATE conversion
17
+ */
18
+ VALUE
19
+ asn1time_to_time(ASN1_TIME *time)
20
+ {
21
+ struct tm tm;
22
+ VALUE argv[6];
23
+
24
+ if (!time || !time->data) return Qnil;
25
+ memset(&tm, 0, sizeof(struct tm));
26
+
27
+ switch (time->type) {
28
+ case V_ASN1_UTCTIME:
29
+ if (sscanf(time->data, "%2d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
30
+ &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
31
+ ossl_raise(rb_eTypeError, "bad UTCTIME format");
32
+ }
33
+ if (tm.tm_year < 69) {
34
+ tm.tm_year += 2000;
35
+ } else {
36
+ tm.tm_year += 1900;
37
+ }
38
+ break;
39
+ case V_ASN1_GENERALIZEDTIME:
40
+ if (sscanf(time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
41
+ &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
42
+ ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" );
43
+ }
44
+ break;
45
+ default:
46
+ rb_warning("unknown time format");
47
+ return Qnil;
48
+ }
49
+ argv[0] = INT2NUM(tm.tm_year);
50
+ argv[1] = INT2NUM(tm.tm_mon);
51
+ argv[2] = INT2NUM(tm.tm_mday);
52
+ argv[3] = INT2NUM(tm.tm_hour);
53
+ argv[4] = INT2NUM(tm.tm_min);
54
+ argv[5] = INT2NUM(tm.tm_sec);
55
+
56
+ return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
57
+ }
58
+
59
+ /*
60
+ * This function is not exported in Ruby's *.h
61
+ */
62
+ extern struct timeval rb_time_timeval(VALUE);
63
+
64
+ time_t
65
+ time_to_time_t(VALUE time)
66
+ {
67
+ return (time_t)NUM2LONG(rb_Integer(time));
68
+ }
69
+
70
+ /*
71
+ * STRING conversion
72
+ */
73
+ VALUE
74
+ asn1str_to_str(ASN1_STRING *str)
75
+ {
76
+ return rb_str_new(str->data, str->length);
77
+ }
78
+
79
+ /*
80
+ * ASN1_INTEGER conversions
81
+ * TODO: Make a decision what's the right way to do this.
82
+ */
83
+ #define DO_IT_VIA_RUBY 0
84
+ VALUE
85
+ asn1integer_to_num(ASN1_INTEGER *ai)
86
+ {
87
+ BIGNUM *bn;
88
+ #if DO_IT_VIA_RUBY
89
+ char *txt;
90
+ #endif
91
+ VALUE num;
92
+
93
+ if (!ai) {
94
+ ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
95
+ }
96
+ if (!(bn = ASN1_INTEGER_to_BN(ai, NULL))) {
97
+ ossl_raise(eOSSLError, NULL);
98
+ }
99
+ #if DO_IT_VIA_RUBY
100
+ if (!(txt = BN_bn2dec(bn))) {
101
+ BN_free(bn);
102
+ ossl_raise(eOSSLError, NULL);
103
+ }
104
+ num = rb_cstr_to_inum(txt, 10, Qtrue);
105
+ OPENSSL_free(txt);
106
+ #else
107
+ num = ossl_bn_new(bn);
108
+ #endif
109
+ BN_free(bn);
110
+
111
+ return num;
112
+ }
113
+
114
+ #if DO_IT_VIA_RUBY
115
+ ASN1_INTEGER *
116
+ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
117
+ {
118
+ BIGNUM *bn = NULL;
119
+
120
+ if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
121
+ bn = GetBNPtr(obj);
122
+ } else {
123
+ obj = rb_String(obj);
124
+ if (!BN_dec2bn(&bn, StringValuePtr(obj))) {
125
+ ossl_raise(eOSSLError, NULL);
126
+ }
127
+ }
128
+ if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
129
+ BN_free(bn);
130
+ ossl_raise(eOSSLError, NULL);
131
+ }
132
+ BN_free(bn);
133
+ return ai;
134
+ }
135
+ #else
136
+ ASN1_INTEGER *
137
+ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
138
+ {
139
+ BIGNUM *bn = GetBNPtr(obj);
140
+
141
+ if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
142
+ ossl_raise(eOSSLError, NULL);
143
+ }
144
+ return ai;
145
+ }
146
+ #endif
147
+
148
+ /********/
149
+ /*
150
+ * ASN1 module
151
+ */
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))
161
+
162
+ VALUE mASN1;
163
+ VALUE eASN1Error;
164
+
165
+ VALUE cASN1Data;
166
+ VALUE cASN1Primitive;
167
+ VALUE cASN1Constructive;
168
+
169
+ VALUE cASN1Boolean; /* BOOLEAN */
170
+ VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
171
+ VALUE cASN1BitString; /* BIT STRING */
172
+ VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
173
+ VALUE cASN1NumericString, cASN1PrintableString;
174
+ VALUE cASN1T61String, cASN1VideotexString;
175
+ VALUE cASN1IA5String, cASN1GraphicString;
176
+ VALUE cASN1ISO64String, cASN1GeneralString;
177
+ VALUE cASN1UniversalString, cASN1BMPString;
178
+ VALUE cASN1Null; /* NULL */
179
+ VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
180
+ VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
181
+ VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
182
+
183
+ static ID sIMPLICIT, sEXPLICIT;
184
+ static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
185
+
186
+ /*
187
+ * Ruby to ASN1 converters
188
+ */
189
+ static ASN1_BOOLEAN
190
+ obj_to_asn1bool(VALUE obj)
191
+ {
192
+ #if OPENSSL_VERSION_NUMBER < 0x00907000L
193
+ return RTEST(obj) ? 0xff : 0x100;
194
+ #else
195
+ return RTEST(obj) ? 0xff : 0x0;
196
+ #endif
197
+ }
198
+
199
+ static ASN1_INTEGER*
200
+ obj_to_asn1int(VALUE obj)
201
+ {
202
+ return num_to_asn1integer(obj, NULL);
203
+ }
204
+
205
+ static ASN1_BIT_STRING*
206
+ obj_to_asn1bstr(VALUE obj, long unused_bits)
207
+ {
208
+ ASN1_BIT_STRING *bstr;
209
+
210
+ if(unused_bits < 0) unused_bits = 0;
211
+ StringValue(obj);
212
+ if(!(bstr = ASN1_BIT_STRING_new()))
213
+ ossl_raise(eASN1Error, NULL);
214
+ ASN1_BIT_STRING_set(bstr, RSTRING_PTR(obj), RSTRING_LEN(obj));
215
+ bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
216
+ bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
217
+
218
+ return bstr;
219
+ }
220
+
221
+ static ASN1_STRING*
222
+ obj_to_asn1str(VALUE obj)
223
+ {
224
+ ASN1_STRING *str;
225
+
226
+ StringValue(obj);
227
+ if(!(str = ASN1_STRING_new()))
228
+ ossl_raise(eASN1Error, NULL);
229
+ ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LEN(obj));
230
+
231
+ return str;
232
+ }
233
+
234
+ static ASN1_NULL*
235
+ obj_to_asn1null(VALUE obj)
236
+ {
237
+ ASN1_NULL *null;
238
+
239
+ if(!NIL_P(obj))
240
+ ossl_raise(eASN1Error, "nil expected");
241
+ if(!(null = ASN1_NULL_new()))
242
+ ossl_raise(eASN1Error, NULL);
243
+
244
+ return null;
245
+ }
246
+
247
+ static ASN1_OBJECT*
248
+ obj_to_asn1obj(VALUE obj)
249
+ {
250
+ ASN1_OBJECT *a1obj;
251
+
252
+ StringValue(obj);
253
+ a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
254
+ if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
255
+ if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
256
+
257
+ return a1obj;
258
+ }
259
+
260
+ static ASN1_UTCTIME*
261
+ obj_to_asn1utime(VALUE time)
262
+ {
263
+ time_t sec;
264
+ ASN1_UTCTIME *t;
265
+
266
+ sec = time_to_time_t(time);
267
+ if(!(t = ASN1_UTCTIME_set(NULL, sec)))
268
+ ossl_raise(eASN1Error, NULL);
269
+
270
+ return t;
271
+ }
272
+
273
+ static ASN1_GENERALIZEDTIME*
274
+ obj_to_asn1gtime(VALUE time)
275
+ {
276
+ time_t sec;
277
+ ASN1_GENERALIZEDTIME *t;
278
+
279
+ sec = time_to_time_t(time);
280
+ if(!(t =ASN1_GENERALIZEDTIME_set(NULL, sec)))
281
+ ossl_raise(eASN1Error, NULL);
282
+
283
+ return t;
284
+ }
285
+
286
+ static ASN1_STRING*
287
+ obj_to_asn1derstr(VALUE obj)
288
+ {
289
+ ASN1_STRING *a1str;
290
+ VALUE str;
291
+
292
+ str = ossl_to_der(obj);
293
+ if(!(a1str = ASN1_STRING_new()))
294
+ ossl_raise(eASN1Error, NULL);
295
+ ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LEN(str));
296
+
297
+ return a1str;
298
+ }
299
+
300
+ /*
301
+ * DER to Ruby converters
302
+ */
303
+ static VALUE
304
+ decode_bool(unsigned char* der, int length)
305
+ {
306
+ int val;
307
+ unsigned const char *p;
308
+
309
+ p = der;
310
+ if((val = d2i_ASN1_BOOLEAN(NULL, &p, length)) < 0)
311
+ ossl_raise(eASN1Error, NULL);
312
+
313
+ return val ? Qtrue : Qfalse;
314
+ }
315
+
316
+ static VALUE
317
+ decode_int(unsigned char* der, int length)
318
+ {
319
+ ASN1_INTEGER *ai;
320
+ unsigned const char *p;
321
+ VALUE ret;
322
+ int status = 0;
323
+
324
+ p = der;
325
+ if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
326
+ ossl_raise(eASN1Error, NULL);
327
+ ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
328
+ (VALUE)ai, &status);
329
+ ASN1_INTEGER_free(ai);
330
+ if(status) rb_jump_tag(status);
331
+
332
+ return ret;
333
+ }
334
+
335
+ static VALUE
336
+ decode_bstr(unsigned char* der, int length, long *unused_bits)
337
+ {
338
+ ASN1_BIT_STRING *bstr;
339
+ const unsigned char *p;
340
+ long len;
341
+ VALUE ret;
342
+
343
+ p = der;
344
+ if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
345
+ ossl_raise(eASN1Error, NULL);
346
+ len = bstr->length;
347
+ *unused_bits = 0;
348
+ if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT)
349
+ *unused_bits = bstr->flags & 0x07;
350
+ ret = rb_str_new((const char *)bstr->data, len);
351
+ ASN1_BIT_STRING_free(bstr);
352
+
353
+ return ret;
354
+ }
355
+
356
+ static VALUE
357
+ decode_enum(unsigned char* der, int length)
358
+ {
359
+ ASN1_ENUMERATED *ai;
360
+ unsigned const char *p;
361
+ VALUE ret;
362
+ int status = 0;
363
+
364
+ p = der;
365
+ if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
366
+ ossl_raise(eASN1Error, NULL);
367
+ ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
368
+ (VALUE)ai, &status);
369
+ ASN1_ENUMERATED_free(ai);
370
+ if(status) rb_jump_tag(status);
371
+
372
+ return ret;
373
+ }
374
+
375
+ static VALUE
376
+ decode_null(unsigned char* der, int length)
377
+ {
378
+ ASN1_NULL *null;
379
+ unsigned char const *p;
380
+
381
+ p = der;
382
+ if(!(null = d2i_ASN1_NULL(NULL, &p, length)))
383
+ ossl_raise(eASN1Error, NULL);
384
+ ASN1_NULL_free(null);
385
+
386
+ return Qnil;
387
+ }
388
+
389
+ static VALUE
390
+ decode_obj(unsigned char* der, int length)
391
+ {
392
+ ASN1_OBJECT *obj;
393
+ unsigned const char *p;
394
+ VALUE ret;
395
+ int nid;
396
+ BIO *bio;
397
+
398
+ p = der;
399
+ if(!(obj = d2i_ASN1_OBJECT(NULL, &p, length)))
400
+ ossl_raise(eASN1Error, NULL);
401
+ if((nid = OBJ_obj2nid(obj)) != NID_undef){
402
+ ASN1_OBJECT_free(obj);
403
+ ret = rb_str_new2(OBJ_nid2sn(nid));
404
+ }
405
+ else{
406
+ if(!(bio = BIO_new(BIO_s_mem()))){
407
+ ASN1_OBJECT_free(obj);
408
+ ossl_raise(eASN1Error, NULL);
409
+ }
410
+ i2a_ASN1_OBJECT(bio, obj);
411
+ ASN1_OBJECT_free(obj);
412
+ ret = ossl_membio2str(bio);
413
+ }
414
+
415
+ return ret;
416
+ }
417
+
418
+ static VALUE
419
+ decode_time(unsigned char* der, int length)
420
+ {
421
+ ASN1_TIME *time;
422
+ unsigned const char *p;
423
+ VALUE ret;
424
+ int status = 0;
425
+
426
+ p = der;
427
+ if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
428
+ ossl_raise(eASN1Error, NULL);
429
+ ret = rb_protect((VALUE(*)_((VALUE)))asn1time_to_time,
430
+ (VALUE)time, &status);
431
+ ASN1_TIME_free(time);
432
+ if(status) rb_jump_tag(status);
433
+
434
+ return ret;
435
+ }
436
+
437
+ /********/
438
+
439
+ typedef struct {
440
+ const char *name;
441
+ VALUE *klass;
442
+ } ossl_asn1_info_t;
443
+
444
+ static ossl_asn1_info_t ossl_asn1_info[] = {
445
+ { "EOC", NULL, }, /* 0 */
446
+ { "BOOLEAN", &cASN1Boolean, }, /* 1 */
447
+ { "INTEGER", &cASN1Integer, }, /* 2 */
448
+ { "BIT_STRING", &cASN1BitString, }, /* 3 */
449
+ { "OCTET_STRING", &cASN1OctetString, }, /* 4 */
450
+ { "NULL", &cASN1Null, }, /* 5 */
451
+ { "OBJECT", &cASN1ObjectId, }, /* 6 */
452
+ { "OBJECT_DESCRIPTOR", NULL, }, /* 7 */
453
+ { "EXTERNAL", NULL, }, /* 8 */
454
+ { "REAL", NULL, }, /* 9 */
455
+ { "ENUMERATED", &cASN1Enumerated, }, /* 10 */
456
+ { "EMBEDDED_PDV", NULL, }, /* 11 */
457
+ { "UTF8STRING", &cASN1UTF8String, }, /* 12 */
458
+ { "RELATIVE_OID", NULL, }, /* 13 */
459
+ { "[UNIVERSAL 14]", NULL, }, /* 14 */
460
+ { "[UNIVERSAL 15]", NULL, }, /* 15 */
461
+ { "SEQUENCE", &cASN1Sequence, }, /* 16 */
462
+ { "SET", &cASN1Set, }, /* 17 */
463
+ { "NUMERICSTRING", &cASN1NumericString, }, /* 18 */
464
+ { "PRINTABLESTRING", &cASN1PrintableString, }, /* 19 */
465
+ { "T61STRING", &cASN1T61String, }, /* 20 */
466
+ { "VIDEOTEXSTRING", &cASN1VideotexString, }, /* 21 */
467
+ { "IA5STRING", &cASN1IA5String, }, /* 22 */
468
+ { "UTCTIME", &cASN1UTCTime, }, /* 23 */
469
+ { "GENERALIZEDTIME", &cASN1GeneralizedTime, }, /* 24 */
470
+ { "GRAPHICSTRING", &cASN1GraphicString, }, /* 25 */
471
+ { "ISO64STRING", &cASN1ISO64String, }, /* 26 */
472
+ { "GENERALSTRING", &cASN1GeneralString, }, /* 27 */
473
+ { "UNIVERSALSTRING", &cASN1UniversalString, }, /* 28 */
474
+ { "CHARACTER_STRING", NULL, }, /* 29 */
475
+ { "BMPSTRING", &cASN1BMPString, }, /* 30 */
476
+ };
477
+
478
+ int ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]));
479
+
480
+ static int ossl_asn1_default_tag(VALUE obj);
481
+
482
+ ASN1_TYPE*
483
+ ossl_asn1_get_asn1type(VALUE obj)
484
+ {
485
+ ASN1_TYPE *ret;
486
+ VALUE value, rflag;
487
+ void *ptr;
488
+ void (*free_func)();
489
+ long tag, flag;
490
+
491
+ tag = ossl_asn1_default_tag(obj);
492
+ value = ossl_asn1_get_value(obj);
493
+ switch(tag){
494
+ case V_ASN1_BOOLEAN:
495
+ ptr = (void*)(VALUE)obj_to_asn1bool(value);
496
+ free_func = NULL;
497
+ break;
498
+ case V_ASN1_INTEGER: /* FALLTHROUGH */
499
+ case V_ASN1_ENUMERATED:
500
+ ptr = obj_to_asn1int(value);
501
+ free_func = ASN1_INTEGER_free;
502
+ break;
503
+ case V_ASN1_BIT_STRING:
504
+ rflag = rb_attr_get(obj, rb_intern("@unused_bits"));
505
+ flag = NIL_P(rflag) ? -1 : NUM2INT(rflag);
506
+ ptr = obj_to_asn1bstr(value, flag);
507
+ free_func = ASN1_BIT_STRING_free;
508
+ break;
509
+ case V_ASN1_NULL:
510
+ ptr = obj_to_asn1null(value);
511
+ free_func = ASN1_NULL_free;
512
+ break;
513
+ case V_ASN1_OCTET_STRING: /* FALLTHROUGH */
514
+ case V_ASN1_UTF8STRING: /* FALLTHROUGH */
515
+ case V_ASN1_NUMERICSTRING: /* FALLTHROUGH */
516
+ case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */
517
+ case V_ASN1_T61STRING: /* FALLTHROUGH */
518
+ case V_ASN1_VIDEOTEXSTRING: /* FALLTHROUGH */
519
+ case V_ASN1_IA5STRING: /* FALLTHROUGH */
520
+ case V_ASN1_GRAPHICSTRING: /* FALLTHROUGH */
521
+ case V_ASN1_ISO64STRING: /* FALLTHROUGH */
522
+ case V_ASN1_GENERALSTRING: /* FALLTHROUGH */
523
+ case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
524
+ case V_ASN1_BMPSTRING:
525
+ ptr = obj_to_asn1str(value);
526
+ free_func = ASN1_STRING_free;
527
+ break;
528
+ case V_ASN1_OBJECT:
529
+ ptr = obj_to_asn1obj(value);
530
+ free_func = ASN1_OBJECT_free;
531
+ break;
532
+ case V_ASN1_UTCTIME:
533
+ ptr = obj_to_asn1utime(value);
534
+ free_func = ASN1_TIME_free;
535
+ break;
536
+ case V_ASN1_GENERALIZEDTIME:
537
+ ptr = obj_to_asn1gtime(value);
538
+ free_func = ASN1_TIME_free;
539
+ break;
540
+ case V_ASN1_SET: /* FALLTHROUGH */
541
+ case V_ASN1_SEQUENCE:
542
+ ptr = obj_to_asn1derstr(obj);
543
+ free_func = ASN1_STRING_free;
544
+ break;
545
+ default:
546
+ ossl_raise(eASN1Error, "unsupported ASN.1 type");
547
+ }
548
+ if(!(ret = OPENSSL_malloc(sizeof(ASN1_TYPE)))){
549
+ if(free_func) free_func(ptr);
550
+ ossl_raise(eASN1Error, "ASN1_TYPE alloc failure");
551
+ }
552
+ memset(ret, 0, sizeof(ASN1_TYPE));
553
+ ASN1_TYPE_set(ret, tag, ptr);
554
+
555
+ return ret;
556
+ }
557
+
558
+ static int
559
+ ossl_asn1_default_tag(VALUE obj)
560
+ {
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
+ }
568
+ }
569
+ ossl_raise(eASN1Error, "universal tag for %s not found",
570
+ rb_class2name(CLASS_OF(obj)));
571
+
572
+ return -1; /* dummy */
573
+ }
574
+
575
+ static int
576
+ ossl_asn1_tag(VALUE obj)
577
+ {
578
+ VALUE tag;
579
+
580
+ tag = ossl_asn1_get_tag(obj);
581
+ if(NIL_P(tag))
582
+ ossl_raise(eASN1Error, "tag number not specified");
583
+
584
+ return NUM2INT(tag);
585
+ }
586
+
587
+ static int
588
+ ossl_asn1_is_explicit(VALUE obj)
589
+ {
590
+ VALUE s;
591
+ int ret = -1;
592
+
593
+ s = ossl_asn1_get_tagging(obj);
594
+ if(NIL_P(s)) return 0;
595
+ else if(SYMBOL_P(s)){
596
+ if (SYM2ID(s) == sIMPLICIT)
597
+ ret = 0;
598
+ else if (SYM2ID(s) == sEXPLICIT)
599
+ ret = 1;
600
+ }
601
+ if(ret < 0){
602
+ ossl_raise(eASN1Error, "invalid tag default");
603
+ }
604
+
605
+ return ret;
606
+ }
607
+
608
+ static int
609
+ ossl_asn1_tag_class(VALUE obj)
610
+ {
611
+ VALUE s;
612
+ int ret = -1;
613
+
614
+ s = ossl_asn1_get_tag_class(obj);
615
+ if(NIL_P(s)) ret = V_ASN1_UNIVERSAL;
616
+ else if(SYMBOL_P(s)){
617
+ if (SYM2ID(s) == sUNIVERSAL)
618
+ ret = V_ASN1_UNIVERSAL;
619
+ else if (SYM2ID(s) == sAPPLICATION)
620
+ ret = V_ASN1_APPLICATION;
621
+ else if (SYM2ID(s) == sCONTEXT_SPECIFIC)
622
+ ret = V_ASN1_CONTEXT_SPECIFIC;
623
+ else if (SYM2ID(s) == sPRIVATE)
624
+ ret = V_ASN1_PRIVATE;
625
+ }
626
+ if(ret < 0){
627
+ ossl_raise(eASN1Error, "invalid tag class");
628
+ }
629
+
630
+ return ret;
631
+ }
632
+
633
+ static VALUE
634
+ ossl_asn1_class2sym(int tc)
635
+ {
636
+ if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
637
+ return ID2SYM(sPRIVATE);
638
+ else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
639
+ return ID2SYM(sCONTEXT_SPECIFIC);
640
+ else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
641
+ return ID2SYM(sAPPLICATION);
642
+ else
643
+ return ID2SYM(sUNIVERSAL);
644
+ }
645
+
646
+ static VALUE
647
+ ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
648
+ {
649
+ if(!SYMBOL_P(tag_class))
650
+ ossl_raise(eASN1Error, "invalid tag class");
651
+ if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31)
652
+ ossl_raise(eASN1Error, "tag number for Universal too large");
653
+ ossl_asn1_set_tag(self, tag);
654
+ ossl_asn1_set_value(self, value);
655
+ ossl_asn1_set_tag_class(self, tag_class);
656
+
657
+ return self;
658
+ }
659
+
660
+ static VALUE
661
+ join_der_i(VALUE i, VALUE str)
662
+ {
663
+ i = ossl_to_der_if_possible(i);
664
+ StringValue(i);
665
+ rb_str_append(str, i);
666
+ return Qnil;
667
+ }
668
+
669
+ static VALUE
670
+ join_der(VALUE enumerable)
671
+ {
672
+ VALUE str = rb_str_new(0, 0);
673
+ rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str);
674
+ return str;
675
+ }
676
+
677
+ static VALUE
678
+ ossl_asn1data_to_der(VALUE self)
679
+ {
680
+ VALUE value, der;
681
+ int tag, tag_class, is_cons = 0;
682
+ long length;
683
+ unsigned char *p;
684
+
685
+ value = ossl_asn1_get_value(self);
686
+ if(rb_obj_is_kind_of(value, rb_cArray)){
687
+ is_cons = 1;
688
+ value = join_der(value);
689
+ }
690
+ StringValue(value);
691
+
692
+ tag = ossl_asn1_tag(self);
693
+ tag_class = ossl_asn1_tag_class(self);
694
+ if((length = ASN1_object_size(1, RSTRING_LEN(value), tag)) <= 0)
695
+ ossl_raise(eASN1Error, NULL);
696
+ der = rb_str_new(0, length);
697
+ p = RSTRING_PTR(der);
698
+ ASN1_put_object(&p, is_cons, RSTRING_LEN(value), tag, tag_class);
699
+ memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
700
+ p += RSTRING_LEN(value);
701
+ ossl_str_adjust(der, p);
702
+
703
+ return der;
704
+ }
705
+
706
+ static VALUE
707
+ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, long depth,
708
+ int once, int yield)
709
+ {
710
+ unsigned char *start, *p;
711
+ long len, off = *offset;
712
+ int hlen, tag, tc, j;
713
+ VALUE ary, asn1data, value, tag_class;
714
+
715
+ ary = rb_ary_new();
716
+ 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);
732
+ }
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);
752
+ }
753
+ else{
754
+ value = rb_str_new(p, len);
755
+ p += len;
756
+ off += len;
757
+ }
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
+ }
790
+ }
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));
794
+ }
795
+ }
796
+ else{
797
+ asn1data = rb_funcall(cASN1Data, rb_intern("new"), 3,
798
+ value, INT2NUM(tag), ID2SYM(tag_class));
799
+ }
800
+ rb_ary_push(ary, asn1data);
801
+ length -= len;
802
+ if(once) break;
803
+ }
804
+ *pp = p;
805
+ *offset = off;
806
+
807
+ return ary;
808
+ }
809
+
810
+ static VALUE
811
+ ossl_asn1_traverse(VALUE self, VALUE obj)
812
+ {
813
+ unsigned char *p;
814
+ long offset = 0;
815
+ volatile VALUE tmp;
816
+
817
+ obj = ossl_to_der_if_possible(obj);
818
+ tmp = rb_str_new4(StringValue(obj));
819
+ p = RSTRING_PTR(tmp);
820
+ ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 1);
821
+
822
+ return Qnil;
823
+ }
824
+
825
+ static VALUE
826
+ ossl_asn1_decode(VALUE self, VALUE obj)
827
+ {
828
+ VALUE ret, ary;
829
+ unsigned char *p;
830
+ long offset = 0;
831
+ volatile VALUE tmp;
832
+
833
+ obj = ossl_to_der_if_possible(obj);
834
+ 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
+
839
+ return ret;
840
+ }
841
+
842
+ static VALUE
843
+ ossl_asn1_decode_all(VALUE self, VALUE obj)
844
+ {
845
+ VALUE ret;
846
+ unsigned char *p;
847
+ long offset = 0;
848
+ volatile VALUE tmp;
849
+
850
+ obj = ossl_to_der_if_possible(obj);
851
+ 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;
856
+ }
857
+
858
+ static VALUE
859
+ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
860
+ {
861
+ VALUE value, tag, tagging, tag_class;
862
+
863
+ rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class);
864
+ if(argc > 1){
865
+ if(NIL_P(tag))
866
+ 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);
873
+ if(!SYMBOL_P(tag_class))
874
+ ossl_raise(eASN1Error, "invalid tag class");
875
+ if(SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
876
+ ossl_raise(eASN1Error, "tag number for Universal too large");
877
+ }
878
+ else{
879
+ tag = INT2NUM(ossl_asn1_default_tag(self));
880
+ tagging = Qnil;
881
+ tag_class = ID2SYM(sUNIVERSAL);
882
+ }
883
+ ossl_asn1_set_tag(self, tag);
884
+ ossl_asn1_set_value(self, value);
885
+ ossl_asn1_set_tagging(self, tagging);
886
+ ossl_asn1_set_tag_class(self, tag_class);
887
+
888
+ return self;
889
+ }
890
+
891
+ static int
892
+ ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp)
893
+ {
894
+ #if OPENSSL_VERSION_NUMBER < 0x00907000L
895
+ if(!a) return 0;
896
+ if(a->type == V_ASN1_BOOLEAN)
897
+ return i2d_ASN1_BOOLEAN(a->value.boolean, pp);
898
+ #endif
899
+ return i2d_ASN1_TYPE(a, pp);
900
+ }
901
+
902
+ static void
903
+ ossl_ASN1_TYPE_free(ASN1_TYPE *a)
904
+ {
905
+ #if OPENSSL_VERSION_NUMBER < 0x00907000L
906
+ if(!a) return;
907
+ if(a->type == V_ASN1_BOOLEAN){
908
+ OPENSSL_free(a);
909
+ return;
910
+ }
911
+ #endif
912
+ ASN1_TYPE_free(a);
913
+ }
914
+
915
+ static VALUE
916
+ ossl_asn1prim_to_der(VALUE self)
917
+ {
918
+ ASN1_TYPE *asn1;
919
+ int tn, tc, explicit;
920
+ long len, reallen;
921
+ unsigned char *buf, *p;
922
+ VALUE str;
923
+
924
+ tn = NUM2INT(ossl_asn1_get_tag(self));
925
+ tc = ossl_asn1_tag_class(self);
926
+ explicit = ossl_asn1_is_explicit(self);
927
+ asn1 = ossl_asn1_get_asn1type(self);
928
+
929
+ len = ASN1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn);
930
+ if(!(buf = OPENSSL_malloc(len))){
931
+ ossl_ASN1_TYPE_free(asn1);
932
+ ossl_raise(eASN1Error, "cannot alloc buffer");
933
+ }
934
+ p = buf;
935
+ if (tc == V_ASN1_UNIVERSAL) {
936
+ ossl_i2d_ASN1_TYPE(asn1, &p);
937
+ } else if (explicit) {
938
+ ASN1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc);
939
+ ossl_i2d_ASN1_TYPE(asn1, &p);
940
+ } else {
941
+ ossl_i2d_ASN1_TYPE(asn1, &p);
942
+ *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED);
943
+ }
944
+ ossl_ASN1_TYPE_free(asn1);
945
+ reallen = p - buf;
946
+ assert(reallen <= len);
947
+ str = ossl_buf2str(buf, reallen); /* buf will be free in ossl_buf2str */
948
+
949
+ return str;
950
+ }
951
+
952
+ static VALUE
953
+ ossl_asn1cons_to_der(VALUE self)
954
+ {
955
+ int tag, tn, tc, explicit;
956
+ long seq_len, length;
957
+ unsigned char *p;
958
+ VALUE value, str;
959
+
960
+ tag = ossl_asn1_default_tag(self);
961
+ tn = NUM2INT(ossl_asn1_get_tag(self));
962
+ tc = ossl_asn1_tag_class(self);
963
+ explicit = ossl_asn1_is_explicit(self);
964
+ value = join_der(ossl_asn1_get_value(self));
965
+
966
+ seq_len = ASN1_object_size(1, RSTRING_LEN(value), tag);
967
+ length = ASN1_object_size(1, seq_len, tn);
968
+ str = rb_str_new(0, length);
969
+ p = RSTRING_PTR(str);
970
+ if(tc == V_ASN1_UNIVERSAL)
971
+ ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
972
+ else{
973
+ 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);
976
+ }
977
+ else ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
978
+ }
979
+ memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
980
+ p += RSTRING_LEN(value);
981
+ ossl_str_adjust(str, p);
982
+
983
+ return str;
984
+ }
985
+
986
+ static VALUE
987
+ ossl_asn1cons_each(VALUE self)
988
+ {
989
+ rb_ary_each(ossl_asn1_get_value(self));
990
+ return self;
991
+ }
992
+
993
+ static VALUE
994
+ ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
995
+ {
996
+ StringValue(oid);
997
+ StringValue(sn);
998
+ StringValue(ln);
999
+
1000
+ if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
1001
+ ossl_raise(eASN1Error, NULL);
1002
+
1003
+ return Qtrue;
1004
+ }
1005
+
1006
+ static VALUE
1007
+ ossl_asn1obj_get_sn(VALUE self)
1008
+ {
1009
+ VALUE val, ret = Qnil;
1010
+ int nid;
1011
+
1012
+ val = ossl_asn1_get_value(self);
1013
+ if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
1014
+ ret = rb_str_new2(OBJ_nid2sn(nid));
1015
+
1016
+ return ret;
1017
+ }
1018
+
1019
+ static VALUE
1020
+ ossl_asn1obj_get_ln(VALUE self)
1021
+ {
1022
+ VALUE val, ret = Qnil;
1023
+ int nid;
1024
+
1025
+ val = ossl_asn1_get_value(self);
1026
+ if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
1027
+ ret = rb_str_new2(OBJ_nid2ln(nid));
1028
+
1029
+ return ret;
1030
+ }
1031
+
1032
+ static VALUE
1033
+ ossl_asn1obj_get_oid(VALUE self)
1034
+ {
1035
+ VALUE val;
1036
+ ASN1_OBJECT *a1obj;
1037
+ char buf[128];
1038
+
1039
+ val = ossl_asn1_get_value(self);
1040
+ a1obj = obj_to_asn1obj(val);
1041
+ OBJ_obj2txt(buf, sizeof(buf), a1obj, 1);
1042
+ ASN1_OBJECT_free(a1obj);
1043
+
1044
+ return rb_str_new2(buf);
1045
+ }
1046
+
1047
+ #define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
1048
+ static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\
1049
+ { return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); }
1050
+
1051
+ OSSL_ASN1_IMPL_FACTORY_METHOD(Boolean)
1052
+ OSSL_ASN1_IMPL_FACTORY_METHOD(Integer)
1053
+ OSSL_ASN1_IMPL_FACTORY_METHOD(Enumerated)
1054
+ OSSL_ASN1_IMPL_FACTORY_METHOD(BitString)
1055
+ OSSL_ASN1_IMPL_FACTORY_METHOD(OctetString)
1056
+ OSSL_ASN1_IMPL_FACTORY_METHOD(UTF8String)
1057
+ OSSL_ASN1_IMPL_FACTORY_METHOD(NumericString)
1058
+ OSSL_ASN1_IMPL_FACTORY_METHOD(PrintableString)
1059
+ OSSL_ASN1_IMPL_FACTORY_METHOD(T61String)
1060
+ OSSL_ASN1_IMPL_FACTORY_METHOD(VideotexString)
1061
+ OSSL_ASN1_IMPL_FACTORY_METHOD(IA5String)
1062
+ OSSL_ASN1_IMPL_FACTORY_METHOD(GraphicString)
1063
+ OSSL_ASN1_IMPL_FACTORY_METHOD(ISO64String)
1064
+ OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralString)
1065
+ OSSL_ASN1_IMPL_FACTORY_METHOD(UniversalString)
1066
+ OSSL_ASN1_IMPL_FACTORY_METHOD(BMPString)
1067
+ OSSL_ASN1_IMPL_FACTORY_METHOD(Null)
1068
+ OSSL_ASN1_IMPL_FACTORY_METHOD(ObjectId)
1069
+ OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime)
1070
+ OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime)
1071
+ OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence)
1072
+ OSSL_ASN1_IMPL_FACTORY_METHOD(Set)
1073
+
1074
+ void
1075
+ Init_ossl_asn1()
1076
+ {
1077
+ VALUE ary;
1078
+ int i;
1079
+
1080
+ #if 0 /* let rdoc know about mOSSL */
1081
+ mOSSL = rb_define_module("OpenSSL");
1082
+ #endif
1083
+
1084
+ sUNIVERSAL = rb_intern("UNIVERSAL");
1085
+ sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
1086
+ sAPPLICATION = rb_intern("APPLICATION");
1087
+ sPRIVATE = rb_intern("PRIVATE");
1088
+ sEXPLICIT = rb_intern("EXPLICIT");
1089
+ sIMPLICIT = rb_intern("IMPLICIT");
1090
+
1091
+ mASN1 = rb_define_module_under(mOSSL, "ASN1");
1092
+ eASN1Error = rb_define_class_under(mASN1, "ASN1Error", eOSSLError);
1093
+ rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1);
1094
+ rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1);
1095
+ rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1);
1096
+ ary = rb_ary_new();
1097
+ rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
1098
+ for(i = 0; i < ossl_asn1_info_size; i++){
1099
+ if(ossl_asn1_info[i].name[0] == '[') continue;
1100
+ rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i));
1101
+ rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name));
1102
+ }
1103
+
1104
+ cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
1105
+ rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
1106
+ rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
1107
+ rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
1108
+ rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
1109
+ rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
1110
+
1111
+ cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data);
1112
+ rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
1113
+ rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
1114
+ rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);
1115
+
1116
+ cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data);
1117
+ rb_include_module(cASN1Constructive, rb_mEnumerable);
1118
+ rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
1119
+ rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
1120
+ rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0);
1121
+ rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0);
1122
+
1123
+ #define OSSL_ASN1_DEFINE_CLASS(name, super) \
1124
+ do{\
1125
+ cASN1##name = rb_define_class_under(mASN1, #name, cASN1##super);\
1126
+ rb_define_module_function(mASN1, #name, ossl_asn1_##name, -1);\
1127
+ }while(0)
1128
+
1129
+ OSSL_ASN1_DEFINE_CLASS(Boolean, Primitive);
1130
+ OSSL_ASN1_DEFINE_CLASS(Integer, Primitive);
1131
+ OSSL_ASN1_DEFINE_CLASS(Enumerated, Primitive);
1132
+ OSSL_ASN1_DEFINE_CLASS(BitString, Primitive);
1133
+ OSSL_ASN1_DEFINE_CLASS(OctetString, Primitive);
1134
+ OSSL_ASN1_DEFINE_CLASS(UTF8String, Primitive);
1135
+ OSSL_ASN1_DEFINE_CLASS(NumericString, Primitive);
1136
+ OSSL_ASN1_DEFINE_CLASS(PrintableString, Primitive);
1137
+ OSSL_ASN1_DEFINE_CLASS(T61String, Primitive);
1138
+ OSSL_ASN1_DEFINE_CLASS(VideotexString, Primitive);
1139
+ OSSL_ASN1_DEFINE_CLASS(IA5String, Primitive);
1140
+ OSSL_ASN1_DEFINE_CLASS(GraphicString, Primitive);
1141
+ OSSL_ASN1_DEFINE_CLASS(ISO64String, Primitive);
1142
+ OSSL_ASN1_DEFINE_CLASS(GeneralString, Primitive);
1143
+ OSSL_ASN1_DEFINE_CLASS(UniversalString, Primitive);
1144
+ OSSL_ASN1_DEFINE_CLASS(BMPString, Primitive);
1145
+ OSSL_ASN1_DEFINE_CLASS(Null, Primitive);
1146
+ OSSL_ASN1_DEFINE_CLASS(ObjectId, Primitive);
1147
+ OSSL_ASN1_DEFINE_CLASS(UTCTime, Primitive);
1148
+ OSSL_ASN1_DEFINE_CLASS(GeneralizedTime, Primitive);
1149
+
1150
+ OSSL_ASN1_DEFINE_CLASS(Sequence, Constructive);
1151
+ OSSL_ASN1_DEFINE_CLASS(Set, Constructive);
1152
+
1153
+ rb_define_singleton_method(cASN1ObjectId, "register", ossl_asn1obj_s_register, 3);
1154
+ rb_define_method(cASN1ObjectId, "sn", ossl_asn1obj_get_sn, 0);
1155
+ rb_define_method(cASN1ObjectId, "ln", ossl_asn1obj_get_ln, 0);
1156
+ rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
1157
+ rb_define_alias(cASN1ObjectId, "short_name", "sn");
1158
+ rb_define_alias(cASN1ObjectId, "long_name", "ln");
1159
+ rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
1160
+ }