openssl 2.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of openssl might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/BSDL +22 -0
- data/CONTRIBUTING.md +130 -0
- data/History.md +118 -0
- data/LICENSE.txt +56 -0
- data/README.md +70 -0
- data/ext/openssl/deprecation.rb +26 -0
- data/ext/openssl/extconf.rb +158 -0
- data/ext/openssl/openssl_missing.c +173 -0
- data/ext/openssl/openssl_missing.h +244 -0
- data/ext/openssl/ossl.c +1201 -0
- data/ext/openssl/ossl.h +222 -0
- data/ext/openssl/ossl_asn1.c +1992 -0
- data/ext/openssl/ossl_asn1.h +66 -0
- data/ext/openssl/ossl_bio.c +87 -0
- data/ext/openssl/ossl_bio.h +19 -0
- data/ext/openssl/ossl_bn.c +1153 -0
- data/ext/openssl/ossl_bn.h +23 -0
- data/ext/openssl/ossl_cipher.c +1085 -0
- data/ext/openssl/ossl_cipher.h +20 -0
- data/ext/openssl/ossl_config.c +89 -0
- data/ext/openssl/ossl_config.h +19 -0
- data/ext/openssl/ossl_digest.c +453 -0
- data/ext/openssl/ossl_digest.h +20 -0
- data/ext/openssl/ossl_engine.c +580 -0
- data/ext/openssl/ossl_engine.h +19 -0
- data/ext/openssl/ossl_hmac.c +398 -0
- data/ext/openssl/ossl_hmac.h +18 -0
- data/ext/openssl/ossl_ns_spki.c +406 -0
- data/ext/openssl/ossl_ns_spki.h +19 -0
- data/ext/openssl/ossl_ocsp.c +2013 -0
- data/ext/openssl/ossl_ocsp.h +23 -0
- data/ext/openssl/ossl_pkcs12.c +259 -0
- data/ext/openssl/ossl_pkcs12.h +13 -0
- data/ext/openssl/ossl_pkcs5.c +180 -0
- data/ext/openssl/ossl_pkcs5.h +6 -0
- data/ext/openssl/ossl_pkcs7.c +1125 -0
- data/ext/openssl/ossl_pkcs7.h +20 -0
- data/ext/openssl/ossl_pkey.c +435 -0
- data/ext/openssl/ossl_pkey.h +245 -0
- data/ext/openssl/ossl_pkey_dh.c +650 -0
- data/ext/openssl/ossl_pkey_dsa.c +672 -0
- data/ext/openssl/ossl_pkey_ec.c +1899 -0
- data/ext/openssl/ossl_pkey_rsa.c +768 -0
- data/ext/openssl/ossl_rand.c +238 -0
- data/ext/openssl/ossl_rand.h +18 -0
- data/ext/openssl/ossl_ssl.c +2679 -0
- data/ext/openssl/ossl_ssl.h +41 -0
- data/ext/openssl/ossl_ssl_session.c +352 -0
- data/ext/openssl/ossl_version.h +15 -0
- data/ext/openssl/ossl_x509.c +186 -0
- data/ext/openssl/ossl_x509.h +119 -0
- data/ext/openssl/ossl_x509attr.c +328 -0
- data/ext/openssl/ossl_x509cert.c +860 -0
- data/ext/openssl/ossl_x509crl.c +565 -0
- data/ext/openssl/ossl_x509ext.c +480 -0
- data/ext/openssl/ossl_x509name.c +547 -0
- data/ext/openssl/ossl_x509req.c +492 -0
- data/ext/openssl/ossl_x509revoked.c +279 -0
- data/ext/openssl/ossl_x509store.c +846 -0
- data/ext/openssl/ruby_missing.h +32 -0
- data/lib/openssl.rb +21 -0
- data/lib/openssl/bn.rb +39 -0
- data/lib/openssl/buffering.rb +451 -0
- data/lib/openssl/cipher.rb +67 -0
- data/lib/openssl/config.rb +473 -0
- data/lib/openssl/digest.rb +78 -0
- data/lib/openssl/pkey.rb +44 -0
- data/lib/openssl/ssl.rb +416 -0
- data/lib/openssl/x509.rb +176 -0
- metadata +178 -0
data/ext/openssl/ossl.h
ADDED
@@ -0,0 +1,222 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' project
|
3
|
+
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#if !defined(_OSSL_H_)
|
11
|
+
#define _OSSL_H_
|
12
|
+
|
13
|
+
#include RUBY_EXTCONF_H
|
14
|
+
|
15
|
+
#if 0
|
16
|
+
mOSSL = rb_define_module("OpenSSL");
|
17
|
+
mX509 = rb_define_module_under(mOSSL, "X509");
|
18
|
+
#endif
|
19
|
+
|
20
|
+
/*
|
21
|
+
* OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
|
22
|
+
*/
|
23
|
+
#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/
|
24
|
+
# undef RFILE
|
25
|
+
#endif
|
26
|
+
#include <ruby.h>
|
27
|
+
#include <ruby/io.h>
|
28
|
+
#include <ruby/thread.h>
|
29
|
+
|
30
|
+
#include <openssl/opensslv.h>
|
31
|
+
|
32
|
+
#ifdef HAVE_ASSERT_H
|
33
|
+
# include <assert.h>
|
34
|
+
#else
|
35
|
+
# define assert(condition)
|
36
|
+
#endif
|
37
|
+
|
38
|
+
#if defined(_WIN32) && !defined(LIBRESSL_VERSION_NUMBER)
|
39
|
+
# include <openssl/e_os2.h>
|
40
|
+
# if !defined(OPENSSL_SYS_WIN32)
|
41
|
+
# define OPENSSL_SYS_WIN32 1
|
42
|
+
# endif
|
43
|
+
# include <winsock2.h>
|
44
|
+
#endif
|
45
|
+
#include <errno.h>
|
46
|
+
#include <openssl/err.h>
|
47
|
+
#include <openssl/asn1.h>
|
48
|
+
#include <openssl/x509v3.h>
|
49
|
+
#include <openssl/ssl.h>
|
50
|
+
#include <openssl/pkcs12.h>
|
51
|
+
#include <openssl/pkcs7.h>
|
52
|
+
#include <openssl/hmac.h>
|
53
|
+
#include <openssl/rand.h>
|
54
|
+
#include <openssl/conf.h>
|
55
|
+
#include <openssl/conf_api.h>
|
56
|
+
#if !defined(_WIN32)
|
57
|
+
# include <openssl/crypto.h>
|
58
|
+
#endif
|
59
|
+
#if !defined(OPENSSL_NO_ENGINE)
|
60
|
+
# include <openssl/engine.h>
|
61
|
+
#endif
|
62
|
+
#if !defined(OPENSSL_NO_OCSP)
|
63
|
+
# include <openssl/ocsp.h>
|
64
|
+
#endif
|
65
|
+
|
66
|
+
/*
|
67
|
+
* Common Module
|
68
|
+
*/
|
69
|
+
extern VALUE mOSSL;
|
70
|
+
|
71
|
+
/*
|
72
|
+
* Common Error Class
|
73
|
+
*/
|
74
|
+
extern VALUE eOSSLError;
|
75
|
+
|
76
|
+
/*
|
77
|
+
* CheckTypes
|
78
|
+
*/
|
79
|
+
#define OSSL_Check_Kind(obj, klass) do {\
|
80
|
+
if (!rb_obj_is_kind_of((obj), (klass))) {\
|
81
|
+
ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected kind of %"PRIsVALUE")",\
|
82
|
+
rb_obj_class(obj), (klass));\
|
83
|
+
}\
|
84
|
+
} while (0)
|
85
|
+
|
86
|
+
#define OSSL_Check_Instance(obj, klass) do {\
|
87
|
+
if (!rb_obj_is_instance_of((obj), (klass))) {\
|
88
|
+
ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected instance of %"PRIsVALUE")",\
|
89
|
+
rb_obj_class(obj), (klass));\
|
90
|
+
}\
|
91
|
+
} while (0)
|
92
|
+
|
93
|
+
#define OSSL_Check_Same_Class(obj1, obj2) do {\
|
94
|
+
if (!rb_obj_is_instance_of((obj1), rb_obj_class(obj2))) {\
|
95
|
+
ossl_raise(rb_eTypeError, "wrong argument type");\
|
96
|
+
}\
|
97
|
+
} while (0)
|
98
|
+
|
99
|
+
/*
|
100
|
+
* Data Conversion
|
101
|
+
*/
|
102
|
+
STACK_OF(X509) *ossl_x509_ary2sk0(VALUE);
|
103
|
+
STACK_OF(X509) *ossl_x509_ary2sk(VALUE);
|
104
|
+
STACK_OF(X509) *ossl_protect_x509_ary2sk(VALUE,int*);
|
105
|
+
VALUE ossl_x509_sk2ary(const STACK_OF(X509) *certs);
|
106
|
+
VALUE ossl_x509crl_sk2ary(const STACK_OF(X509_CRL) *crl);
|
107
|
+
VALUE ossl_x509name_sk2ary(const STACK_OF(X509_NAME) *names);
|
108
|
+
VALUE ossl_buf2str(char *buf, int len);
|
109
|
+
#define ossl_str_adjust(str, p) \
|
110
|
+
do{\
|
111
|
+
long len = RSTRING_LEN(str);\
|
112
|
+
long newlen = (long)((p) - (unsigned char*)RSTRING_PTR(str));\
|
113
|
+
assert(newlen <= len);\
|
114
|
+
rb_str_set_len((str), newlen);\
|
115
|
+
}while(0)
|
116
|
+
/*
|
117
|
+
* Convert binary string to hex string. The caller is responsible for
|
118
|
+
* ensuring out has (2 * len) bytes of capacity.
|
119
|
+
*/
|
120
|
+
void ossl_bin2hex(unsigned char *in, char *out, size_t len);
|
121
|
+
|
122
|
+
/*
|
123
|
+
* Our default PEM callback
|
124
|
+
*/
|
125
|
+
/* Convert the argument to String and validate the length. Note this may raise. */
|
126
|
+
VALUE ossl_pem_passwd_value(VALUE);
|
127
|
+
/* Can be casted to pem_password_cb. If a password (String) is passed as the
|
128
|
+
* "arbitrary data" (typically the last parameter of PEM_{read,write}_
|
129
|
+
* functions), uses the value. If not, but a block is given, yields to it.
|
130
|
+
* If not either, fallbacks to PEM_def_callback() which reads from stdin. */
|
131
|
+
int ossl_pem_passwd_cb(char *, int, int, void *);
|
132
|
+
|
133
|
+
/*
|
134
|
+
* Clear BIO* with this in PEM/DER fallback scenarios to avoid decoding
|
135
|
+
* errors piling up in OpenSSL::Errors
|
136
|
+
*/
|
137
|
+
#define OSSL_BIO_reset(bio) do { \
|
138
|
+
(void)BIO_reset((bio)); \
|
139
|
+
ossl_clear_error(); \
|
140
|
+
} while (0)
|
141
|
+
|
142
|
+
/*
|
143
|
+
* ERRor messages
|
144
|
+
*/
|
145
|
+
#define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error())
|
146
|
+
NORETURN(void ossl_raise(VALUE, const char *, ...));
|
147
|
+
VALUE ossl_exc_new(VALUE, const char *, ...);
|
148
|
+
/* Clear OpenSSL error queue. If dOSSL is set, rb_warn() them. */
|
149
|
+
void ossl_clear_error(void);
|
150
|
+
|
151
|
+
/*
|
152
|
+
* Verify callback
|
153
|
+
*/
|
154
|
+
extern int ossl_store_ctx_ex_verify_cb_idx;
|
155
|
+
extern int ossl_store_ex_verify_cb_idx;
|
156
|
+
|
157
|
+
int ossl_verify_cb_call(VALUE, int, X509_STORE_CTX *);
|
158
|
+
|
159
|
+
/*
|
160
|
+
* String to DER String
|
161
|
+
*/
|
162
|
+
extern ID ossl_s_to_der;
|
163
|
+
VALUE ossl_to_der(VALUE);
|
164
|
+
VALUE ossl_to_der_if_possible(VALUE);
|
165
|
+
|
166
|
+
/*
|
167
|
+
* Debug
|
168
|
+
*/
|
169
|
+
extern VALUE dOSSL;
|
170
|
+
|
171
|
+
#if defined(HAVE_VA_ARGS_MACRO)
|
172
|
+
#define OSSL_Debug(...) do { \
|
173
|
+
if (dOSSL == Qtrue) { \
|
174
|
+
fprintf(stderr, "OSSL_DEBUG: "); \
|
175
|
+
fprintf(stderr, __VA_ARGS__); \
|
176
|
+
fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \
|
177
|
+
} \
|
178
|
+
} while (0)
|
179
|
+
|
180
|
+
#define OSSL_Warning(fmt, ...) do { \
|
181
|
+
OSSL_Debug((fmt), ##__VA_ARGS__); \
|
182
|
+
rb_warning((fmt), ##__VA_ARGS__); \
|
183
|
+
} while (0)
|
184
|
+
|
185
|
+
#define OSSL_Warn(fmt, ...) do { \
|
186
|
+
OSSL_Debug((fmt), ##__VA_ARGS__); \
|
187
|
+
rb_warn((fmt), ##__VA_ARGS__); \
|
188
|
+
} while (0)
|
189
|
+
#else
|
190
|
+
void ossl_debug(const char *, ...);
|
191
|
+
#define OSSL_Debug ossl_debug
|
192
|
+
#define OSSL_Warning rb_warning
|
193
|
+
#define OSSL_Warn rb_warn
|
194
|
+
#endif
|
195
|
+
|
196
|
+
/*
|
197
|
+
* Include all parts
|
198
|
+
*/
|
199
|
+
#include "openssl_missing.h"
|
200
|
+
#include "ruby_missing.h"
|
201
|
+
#include "ossl_asn1.h"
|
202
|
+
#include "ossl_bio.h"
|
203
|
+
#include "ossl_bn.h"
|
204
|
+
#include "ossl_cipher.h"
|
205
|
+
#include "ossl_config.h"
|
206
|
+
#include "ossl_digest.h"
|
207
|
+
#include "ossl_hmac.h"
|
208
|
+
#include "ossl_ns_spki.h"
|
209
|
+
#include "ossl_ocsp.h"
|
210
|
+
#include "ossl_pkcs12.h"
|
211
|
+
#include "ossl_pkcs7.h"
|
212
|
+
#include "ossl_pkcs5.h"
|
213
|
+
#include "ossl_pkey.h"
|
214
|
+
#include "ossl_rand.h"
|
215
|
+
#include "ossl_ssl.h"
|
216
|
+
#include "ossl_version.h"
|
217
|
+
#include "ossl_x509.h"
|
218
|
+
#include "ossl_engine.h"
|
219
|
+
|
220
|
+
void Init_openssl(void);
|
221
|
+
|
222
|
+
#endif /* _OSSL_H_ */
|
@@ -0,0 +1,1992 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' team members
|
3
|
+
* Copyright (C) 2003
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#include "ossl.h"
|
11
|
+
|
12
|
+
#if defined(HAVE_SYS_TIME_H)
|
13
|
+
# include <sys/time.h>
|
14
|
+
#elif !defined(NT) && !defined(_WIN32)
|
15
|
+
struct timeval {
|
16
|
+
long tv_sec; /* seconds */
|
17
|
+
long tv_usec; /* and microseconds */
|
18
|
+
};
|
19
|
+
#endif
|
20
|
+
|
21
|
+
static VALUE join_der(VALUE enumerable);
|
22
|
+
static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset,
|
23
|
+
int depth, int yield, long *num_read);
|
24
|
+
static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self);
|
25
|
+
static VALUE ossl_asn1eoc_initialize(VALUE self);
|
26
|
+
|
27
|
+
/*
|
28
|
+
* DATE conversion
|
29
|
+
*/
|
30
|
+
VALUE
|
31
|
+
asn1time_to_time(const ASN1_TIME *time)
|
32
|
+
{
|
33
|
+
struct tm tm;
|
34
|
+
VALUE argv[6];
|
35
|
+
int count;
|
36
|
+
|
37
|
+
if (!time || !time->data) return Qnil;
|
38
|
+
memset(&tm, 0, sizeof(struct tm));
|
39
|
+
|
40
|
+
switch (time->type) {
|
41
|
+
case V_ASN1_UTCTIME:
|
42
|
+
count = sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ",
|
43
|
+
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min,
|
44
|
+
&tm.tm_sec);
|
45
|
+
|
46
|
+
if (count == 5) {
|
47
|
+
tm.tm_sec = 0;
|
48
|
+
} else if (count != 6) {
|
49
|
+
ossl_raise(rb_eTypeError, "bad UTCTIME format: \"%s\"",
|
50
|
+
time->data);
|
51
|
+
}
|
52
|
+
if (tm.tm_year < 69) {
|
53
|
+
tm.tm_year += 2000;
|
54
|
+
} else {
|
55
|
+
tm.tm_year += 1900;
|
56
|
+
}
|
57
|
+
break;
|
58
|
+
case V_ASN1_GENERALIZEDTIME:
|
59
|
+
if (sscanf((const char *)time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
|
60
|
+
&tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
|
61
|
+
ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" );
|
62
|
+
}
|
63
|
+
break;
|
64
|
+
default:
|
65
|
+
rb_warning("unknown time format");
|
66
|
+
return Qnil;
|
67
|
+
}
|
68
|
+
argv[0] = INT2NUM(tm.tm_year);
|
69
|
+
argv[1] = INT2NUM(tm.tm_mon);
|
70
|
+
argv[2] = INT2NUM(tm.tm_mday);
|
71
|
+
argv[3] = INT2NUM(tm.tm_hour);
|
72
|
+
argv[4] = INT2NUM(tm.tm_min);
|
73
|
+
argv[5] = INT2NUM(tm.tm_sec);
|
74
|
+
|
75
|
+
return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
|
76
|
+
}
|
77
|
+
|
78
|
+
#if defined(HAVE_ASN1_TIME_ADJ)
|
79
|
+
void
|
80
|
+
ossl_time_split(VALUE time, time_t *sec, int *days)
|
81
|
+
{
|
82
|
+
VALUE num = rb_Integer(time);
|
83
|
+
|
84
|
+
if (FIXNUM_P(num)) {
|
85
|
+
time_t t = FIX2LONG(num);
|
86
|
+
*sec = t % 86400;
|
87
|
+
*days = rb_long2int(t / 86400);
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
*days = NUM2INT(rb_funcall(num, rb_intern("/"), 1, INT2FIX(86400)));
|
91
|
+
*sec = NUM2TIMET(rb_funcall(num, rb_intern("%"), 1, INT2FIX(86400)));
|
92
|
+
}
|
93
|
+
}
|
94
|
+
#else
|
95
|
+
time_t
|
96
|
+
time_to_time_t(VALUE time)
|
97
|
+
{
|
98
|
+
return (time_t)NUM2TIMET(rb_Integer(time));
|
99
|
+
}
|
100
|
+
#endif
|
101
|
+
|
102
|
+
/*
|
103
|
+
* STRING conversion
|
104
|
+
*/
|
105
|
+
VALUE
|
106
|
+
asn1str_to_str(const ASN1_STRING *str)
|
107
|
+
{
|
108
|
+
return rb_str_new((const char *)str->data, str->length);
|
109
|
+
}
|
110
|
+
|
111
|
+
/*
|
112
|
+
* ASN1_INTEGER conversions
|
113
|
+
* TODO: Make a decision what's the right way to do this.
|
114
|
+
*/
|
115
|
+
#define DO_IT_VIA_RUBY 0
|
116
|
+
VALUE
|
117
|
+
asn1integer_to_num(const ASN1_INTEGER *ai)
|
118
|
+
{
|
119
|
+
BIGNUM *bn;
|
120
|
+
#if DO_IT_VIA_RUBY
|
121
|
+
char *txt;
|
122
|
+
#endif
|
123
|
+
VALUE num;
|
124
|
+
|
125
|
+
if (!ai) {
|
126
|
+
ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
|
127
|
+
}
|
128
|
+
if (ai->type == V_ASN1_ENUMERATED)
|
129
|
+
/* const_cast: workaround for old OpenSSL */
|
130
|
+
bn = ASN1_ENUMERATED_to_BN((ASN1_ENUMERATED *)ai, NULL);
|
131
|
+
else
|
132
|
+
bn = ASN1_INTEGER_to_BN(ai, NULL);
|
133
|
+
|
134
|
+
if (!bn)
|
135
|
+
ossl_raise(eOSSLError, NULL);
|
136
|
+
#if DO_IT_VIA_RUBY
|
137
|
+
if (!(txt = BN_bn2dec(bn))) {
|
138
|
+
BN_free(bn);
|
139
|
+
ossl_raise(eOSSLError, NULL);
|
140
|
+
}
|
141
|
+
num = rb_cstr_to_inum(txt, 10, Qtrue);
|
142
|
+
OPENSSL_free(txt);
|
143
|
+
#else
|
144
|
+
num = ossl_bn_new(bn);
|
145
|
+
#endif
|
146
|
+
BN_free(bn);
|
147
|
+
|
148
|
+
return num;
|
149
|
+
}
|
150
|
+
|
151
|
+
#if DO_IT_VIA_RUBY
|
152
|
+
ASN1_INTEGER *
|
153
|
+
num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
|
154
|
+
{
|
155
|
+
BIGNUM *bn = NULL;
|
156
|
+
|
157
|
+
if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
|
158
|
+
bn = GetBNPtr(obj);
|
159
|
+
} else {
|
160
|
+
obj = rb_String(obj);
|
161
|
+
if (!BN_dec2bn(&bn, StringValueCStr(obj))) {
|
162
|
+
ossl_raise(eOSSLError, NULL);
|
163
|
+
}
|
164
|
+
}
|
165
|
+
if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
|
166
|
+
BN_free(bn);
|
167
|
+
ossl_raise(eOSSLError, NULL);
|
168
|
+
}
|
169
|
+
BN_free(bn);
|
170
|
+
return ai;
|
171
|
+
}
|
172
|
+
#else
|
173
|
+
ASN1_INTEGER *
|
174
|
+
num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
|
175
|
+
{
|
176
|
+
BIGNUM *bn;
|
177
|
+
|
178
|
+
if (NIL_P(obj))
|
179
|
+
ossl_raise(rb_eTypeError, "Can't convert nil into Integer");
|
180
|
+
|
181
|
+
bn = GetBNPtr(obj);
|
182
|
+
|
183
|
+
if (!(ai = BN_to_ASN1_INTEGER(bn, ai)))
|
184
|
+
ossl_raise(eOSSLError, NULL);
|
185
|
+
|
186
|
+
return ai;
|
187
|
+
}
|
188
|
+
#endif
|
189
|
+
|
190
|
+
/********/
|
191
|
+
/*
|
192
|
+
* ASN1 module
|
193
|
+
*/
|
194
|
+
#define ossl_asn1_get_value(o) rb_attr_get((o),sivVALUE)
|
195
|
+
#define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG)
|
196
|
+
#define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING)
|
197
|
+
#define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS)
|
198
|
+
#define ossl_asn1_get_infinite_length(o) rb_attr_get((o),sivINFINITE_LENGTH)
|
199
|
+
|
200
|
+
#define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v))
|
201
|
+
#define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v))
|
202
|
+
#define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v))
|
203
|
+
#define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v))
|
204
|
+
#define ossl_asn1_set_infinite_length(o,v) rb_ivar_set((o),sivINFINITE_LENGTH,(v))
|
205
|
+
|
206
|
+
VALUE mASN1;
|
207
|
+
VALUE eASN1Error;
|
208
|
+
|
209
|
+
VALUE cASN1Data;
|
210
|
+
VALUE cASN1Primitive;
|
211
|
+
VALUE cASN1Constructive;
|
212
|
+
|
213
|
+
VALUE cASN1EndOfContent;
|
214
|
+
VALUE cASN1Boolean; /* BOOLEAN */
|
215
|
+
VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
|
216
|
+
VALUE cASN1BitString; /* BIT STRING */
|
217
|
+
VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
|
218
|
+
VALUE cASN1NumericString, cASN1PrintableString;
|
219
|
+
VALUE cASN1T61String, cASN1VideotexString;
|
220
|
+
VALUE cASN1IA5String, cASN1GraphicString;
|
221
|
+
VALUE cASN1ISO64String, cASN1GeneralString;
|
222
|
+
VALUE cASN1UniversalString, cASN1BMPString;
|
223
|
+
VALUE cASN1Null; /* NULL */
|
224
|
+
VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
|
225
|
+
VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
|
226
|
+
VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
|
227
|
+
|
228
|
+
static ID sIMPLICIT, sEXPLICIT;
|
229
|
+
static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
|
230
|
+
static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINFINITE_LENGTH, sivUNUSED_BITS;
|
231
|
+
|
232
|
+
/*
|
233
|
+
* Ruby to ASN1 converters
|
234
|
+
*/
|
235
|
+
static ASN1_BOOLEAN
|
236
|
+
obj_to_asn1bool(VALUE obj)
|
237
|
+
{
|
238
|
+
if (NIL_P(obj))
|
239
|
+
ossl_raise(rb_eTypeError, "Can't convert nil into Boolean");
|
240
|
+
|
241
|
+
return RTEST(obj) ? 0xff : 0x0;
|
242
|
+
}
|
243
|
+
|
244
|
+
static ASN1_INTEGER*
|
245
|
+
obj_to_asn1int(VALUE obj)
|
246
|
+
{
|
247
|
+
return num_to_asn1integer(obj, NULL);
|
248
|
+
}
|
249
|
+
|
250
|
+
static ASN1_BIT_STRING*
|
251
|
+
obj_to_asn1bstr(VALUE obj, long unused_bits)
|
252
|
+
{
|
253
|
+
ASN1_BIT_STRING *bstr;
|
254
|
+
|
255
|
+
if(unused_bits < 0) unused_bits = 0;
|
256
|
+
StringValue(obj);
|
257
|
+
if(!(bstr = ASN1_BIT_STRING_new()))
|
258
|
+
ossl_raise(eASN1Error, NULL);
|
259
|
+
ASN1_BIT_STRING_set(bstr, (unsigned char *)RSTRING_PTR(obj), RSTRING_LENINT(obj));
|
260
|
+
bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
|
261
|
+
bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
|
262
|
+
|
263
|
+
return bstr;
|
264
|
+
}
|
265
|
+
|
266
|
+
static ASN1_STRING*
|
267
|
+
obj_to_asn1str(VALUE obj)
|
268
|
+
{
|
269
|
+
ASN1_STRING *str;
|
270
|
+
|
271
|
+
StringValue(obj);
|
272
|
+
if(!(str = ASN1_STRING_new()))
|
273
|
+
ossl_raise(eASN1Error, NULL);
|
274
|
+
ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LENINT(obj));
|
275
|
+
|
276
|
+
return str;
|
277
|
+
}
|
278
|
+
|
279
|
+
static ASN1_NULL*
|
280
|
+
obj_to_asn1null(VALUE obj)
|
281
|
+
{
|
282
|
+
ASN1_NULL *null;
|
283
|
+
|
284
|
+
if(!NIL_P(obj))
|
285
|
+
ossl_raise(eASN1Error, "nil expected");
|
286
|
+
if(!(null = ASN1_NULL_new()))
|
287
|
+
ossl_raise(eASN1Error, NULL);
|
288
|
+
|
289
|
+
return null;
|
290
|
+
}
|
291
|
+
|
292
|
+
static ASN1_OBJECT*
|
293
|
+
obj_to_asn1obj(VALUE obj)
|
294
|
+
{
|
295
|
+
ASN1_OBJECT *a1obj;
|
296
|
+
|
297
|
+
StringValueCStr(obj);
|
298
|
+
a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
|
299
|
+
if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
|
300
|
+
if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID %"PRIsVALUE, obj);
|
301
|
+
|
302
|
+
return a1obj;
|
303
|
+
}
|
304
|
+
|
305
|
+
static ASN1_UTCTIME *
|
306
|
+
obj_to_asn1utime(VALUE time)
|
307
|
+
{
|
308
|
+
time_t sec;
|
309
|
+
ASN1_UTCTIME *t;
|
310
|
+
|
311
|
+
#if defined(HAVE_ASN1_TIME_ADJ)
|
312
|
+
int off_days;
|
313
|
+
|
314
|
+
ossl_time_split(time, &sec, &off_days);
|
315
|
+
if (!(t = ASN1_UTCTIME_adj(NULL, sec, off_days, 0)))
|
316
|
+
#else
|
317
|
+
sec = time_to_time_t(time);
|
318
|
+
if (!(t = ASN1_UTCTIME_set(NULL, sec)))
|
319
|
+
#endif
|
320
|
+
ossl_raise(eASN1Error, NULL);
|
321
|
+
|
322
|
+
return t;
|
323
|
+
}
|
324
|
+
|
325
|
+
static ASN1_GENERALIZEDTIME *
|
326
|
+
obj_to_asn1gtime(VALUE time)
|
327
|
+
{
|
328
|
+
time_t sec;
|
329
|
+
ASN1_GENERALIZEDTIME *t;
|
330
|
+
|
331
|
+
#if defined(HAVE_ASN1_TIME_ADJ)
|
332
|
+
int off_days;
|
333
|
+
|
334
|
+
ossl_time_split(time, &sec, &off_days);
|
335
|
+
if (!(t = ASN1_GENERALIZEDTIME_adj(NULL, sec, off_days, 0)))
|
336
|
+
#else
|
337
|
+
sec = time_to_time_t(time);
|
338
|
+
if (!(t = ASN1_GENERALIZEDTIME_set(NULL, sec)))
|
339
|
+
#endif
|
340
|
+
ossl_raise(eASN1Error, NULL);
|
341
|
+
|
342
|
+
return t;
|
343
|
+
}
|
344
|
+
|
345
|
+
static ASN1_STRING*
|
346
|
+
obj_to_asn1derstr(VALUE obj)
|
347
|
+
{
|
348
|
+
ASN1_STRING *a1str;
|
349
|
+
VALUE str;
|
350
|
+
|
351
|
+
str = ossl_to_der(obj);
|
352
|
+
if(!(a1str = ASN1_STRING_new()))
|
353
|
+
ossl_raise(eASN1Error, NULL);
|
354
|
+
ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LENINT(str));
|
355
|
+
|
356
|
+
return a1str;
|
357
|
+
}
|
358
|
+
|
359
|
+
/*
|
360
|
+
* DER to Ruby converters
|
361
|
+
*/
|
362
|
+
static VALUE
|
363
|
+
decode_bool(unsigned char* der, long length)
|
364
|
+
{
|
365
|
+
const unsigned char *p = der;
|
366
|
+
|
367
|
+
assert(length == 3);
|
368
|
+
if (*p++ != 1)
|
369
|
+
ossl_raise(eASN1Error, "not a boolean");
|
370
|
+
if (*p++ != 1)
|
371
|
+
ossl_raise(eASN1Error, "length is not 1");
|
372
|
+
|
373
|
+
return *p ? Qtrue : Qfalse;
|
374
|
+
}
|
375
|
+
|
376
|
+
static VALUE
|
377
|
+
decode_int(unsigned char* der, long length)
|
378
|
+
{
|
379
|
+
ASN1_INTEGER *ai;
|
380
|
+
const unsigned char *p;
|
381
|
+
VALUE ret;
|
382
|
+
int status = 0;
|
383
|
+
|
384
|
+
p = der;
|
385
|
+
if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
|
386
|
+
ossl_raise(eASN1Error, NULL);
|
387
|
+
ret = rb_protect((VALUE (*)(VALUE))asn1integer_to_num,
|
388
|
+
(VALUE)ai, &status);
|
389
|
+
ASN1_INTEGER_free(ai);
|
390
|
+
if(status) rb_jump_tag(status);
|
391
|
+
|
392
|
+
return ret;
|
393
|
+
}
|
394
|
+
|
395
|
+
static VALUE
|
396
|
+
decode_bstr(unsigned char* der, long length, long *unused_bits)
|
397
|
+
{
|
398
|
+
ASN1_BIT_STRING *bstr;
|
399
|
+
const unsigned char *p;
|
400
|
+
long len;
|
401
|
+
VALUE ret;
|
402
|
+
|
403
|
+
p = der;
|
404
|
+
if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
|
405
|
+
ossl_raise(eASN1Error, NULL);
|
406
|
+
len = bstr->length;
|
407
|
+
*unused_bits = 0;
|
408
|
+
if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT)
|
409
|
+
*unused_bits = bstr->flags & 0x07;
|
410
|
+
ret = rb_str_new((const char *)bstr->data, len);
|
411
|
+
ASN1_BIT_STRING_free(bstr);
|
412
|
+
|
413
|
+
return ret;
|
414
|
+
}
|
415
|
+
|
416
|
+
static VALUE
|
417
|
+
decode_enum(unsigned char* der, long length)
|
418
|
+
{
|
419
|
+
ASN1_ENUMERATED *ai;
|
420
|
+
const unsigned char *p;
|
421
|
+
VALUE ret;
|
422
|
+
int status = 0;
|
423
|
+
|
424
|
+
p = der;
|
425
|
+
if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
|
426
|
+
ossl_raise(eASN1Error, NULL);
|
427
|
+
ret = rb_protect((VALUE (*)(VALUE))asn1integer_to_num,
|
428
|
+
(VALUE)ai, &status);
|
429
|
+
ASN1_ENUMERATED_free(ai);
|
430
|
+
if(status) rb_jump_tag(status);
|
431
|
+
|
432
|
+
return ret;
|
433
|
+
}
|
434
|
+
|
435
|
+
static VALUE
|
436
|
+
decode_null(unsigned char* der, long length)
|
437
|
+
{
|
438
|
+
ASN1_NULL *null;
|
439
|
+
const unsigned char *p;
|
440
|
+
|
441
|
+
p = der;
|
442
|
+
if(!(null = d2i_ASN1_NULL(NULL, &p, length)))
|
443
|
+
ossl_raise(eASN1Error, NULL);
|
444
|
+
ASN1_NULL_free(null);
|
445
|
+
|
446
|
+
return Qnil;
|
447
|
+
}
|
448
|
+
|
449
|
+
static VALUE
|
450
|
+
decode_obj(unsigned char* der, long length)
|
451
|
+
{
|
452
|
+
ASN1_OBJECT *obj;
|
453
|
+
const unsigned char *p;
|
454
|
+
VALUE ret;
|
455
|
+
int nid;
|
456
|
+
BIO *bio;
|
457
|
+
|
458
|
+
p = der;
|
459
|
+
if(!(obj = d2i_ASN1_OBJECT(NULL, &p, length)))
|
460
|
+
ossl_raise(eASN1Error, NULL);
|
461
|
+
if((nid = OBJ_obj2nid(obj)) != NID_undef){
|
462
|
+
ASN1_OBJECT_free(obj);
|
463
|
+
ret = rb_str_new2(OBJ_nid2sn(nid));
|
464
|
+
}
|
465
|
+
else{
|
466
|
+
if(!(bio = BIO_new(BIO_s_mem()))){
|
467
|
+
ASN1_OBJECT_free(obj);
|
468
|
+
ossl_raise(eASN1Error, NULL);
|
469
|
+
}
|
470
|
+
i2a_ASN1_OBJECT(bio, obj);
|
471
|
+
ASN1_OBJECT_free(obj);
|
472
|
+
ret = ossl_membio2str(bio);
|
473
|
+
}
|
474
|
+
|
475
|
+
return ret;
|
476
|
+
}
|
477
|
+
|
478
|
+
static VALUE
|
479
|
+
decode_time(unsigned char* der, long length)
|
480
|
+
{
|
481
|
+
ASN1_TIME *time;
|
482
|
+
const unsigned char *p;
|
483
|
+
VALUE ret;
|
484
|
+
int status = 0;
|
485
|
+
|
486
|
+
p = der;
|
487
|
+
if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
|
488
|
+
ossl_raise(eASN1Error, NULL);
|
489
|
+
ret = rb_protect((VALUE (*)(VALUE))asn1time_to_time,
|
490
|
+
(VALUE)time, &status);
|
491
|
+
ASN1_TIME_free(time);
|
492
|
+
if(status) rb_jump_tag(status);
|
493
|
+
|
494
|
+
return ret;
|
495
|
+
}
|
496
|
+
|
497
|
+
static VALUE
|
498
|
+
decode_eoc(unsigned char *der, long length)
|
499
|
+
{
|
500
|
+
if (length != 2 || !(der[0] == 0x00 && der[1] == 0x00))
|
501
|
+
ossl_raise(eASN1Error, NULL);
|
502
|
+
|
503
|
+
return rb_str_new("", 0);
|
504
|
+
}
|
505
|
+
|
506
|
+
/********/
|
507
|
+
|
508
|
+
typedef struct {
|
509
|
+
const char *name;
|
510
|
+
VALUE *klass;
|
511
|
+
} ossl_asn1_info_t;
|
512
|
+
|
513
|
+
static const ossl_asn1_info_t ossl_asn1_info[] = {
|
514
|
+
{ "EOC", &cASN1EndOfContent, }, /* 0 */
|
515
|
+
{ "BOOLEAN", &cASN1Boolean, }, /* 1 */
|
516
|
+
{ "INTEGER", &cASN1Integer, }, /* 2 */
|
517
|
+
{ "BIT_STRING", &cASN1BitString, }, /* 3 */
|
518
|
+
{ "OCTET_STRING", &cASN1OctetString, }, /* 4 */
|
519
|
+
{ "NULL", &cASN1Null, }, /* 5 */
|
520
|
+
{ "OBJECT", &cASN1ObjectId, }, /* 6 */
|
521
|
+
{ "OBJECT_DESCRIPTOR", NULL, }, /* 7 */
|
522
|
+
{ "EXTERNAL", NULL, }, /* 8 */
|
523
|
+
{ "REAL", NULL, }, /* 9 */
|
524
|
+
{ "ENUMERATED", &cASN1Enumerated, }, /* 10 */
|
525
|
+
{ "EMBEDDED_PDV", NULL, }, /* 11 */
|
526
|
+
{ "UTF8STRING", &cASN1UTF8String, }, /* 12 */
|
527
|
+
{ "RELATIVE_OID", NULL, }, /* 13 */
|
528
|
+
{ "[UNIVERSAL 14]", NULL, }, /* 14 */
|
529
|
+
{ "[UNIVERSAL 15]", NULL, }, /* 15 */
|
530
|
+
{ "SEQUENCE", &cASN1Sequence, }, /* 16 */
|
531
|
+
{ "SET", &cASN1Set, }, /* 17 */
|
532
|
+
{ "NUMERICSTRING", &cASN1NumericString, }, /* 18 */
|
533
|
+
{ "PRINTABLESTRING", &cASN1PrintableString, }, /* 19 */
|
534
|
+
{ "T61STRING", &cASN1T61String, }, /* 20 */
|
535
|
+
{ "VIDEOTEXSTRING", &cASN1VideotexString, }, /* 21 */
|
536
|
+
{ "IA5STRING", &cASN1IA5String, }, /* 22 */
|
537
|
+
{ "UTCTIME", &cASN1UTCTime, }, /* 23 */
|
538
|
+
{ "GENERALIZEDTIME", &cASN1GeneralizedTime, }, /* 24 */
|
539
|
+
{ "GRAPHICSTRING", &cASN1GraphicString, }, /* 25 */
|
540
|
+
{ "ISO64STRING", &cASN1ISO64String, }, /* 26 */
|
541
|
+
{ "GENERALSTRING", &cASN1GeneralString, }, /* 27 */
|
542
|
+
{ "UNIVERSALSTRING", &cASN1UniversalString, }, /* 28 */
|
543
|
+
{ "CHARACTER_STRING", NULL, }, /* 29 */
|
544
|
+
{ "BMPSTRING", &cASN1BMPString, }, /* 30 */
|
545
|
+
};
|
546
|
+
|
547
|
+
enum {ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]))};
|
548
|
+
|
549
|
+
static VALUE class_tag_map;
|
550
|
+
|
551
|
+
static int ossl_asn1_default_tag(VALUE obj);
|
552
|
+
|
553
|
+
ASN1_TYPE*
|
554
|
+
ossl_asn1_get_asn1type(VALUE obj)
|
555
|
+
{
|
556
|
+
ASN1_TYPE *ret;
|
557
|
+
VALUE value, rflag;
|
558
|
+
void *ptr;
|
559
|
+
void (*free_func)();
|
560
|
+
int tag, flag;
|
561
|
+
|
562
|
+
tag = ossl_asn1_default_tag(obj);
|
563
|
+
value = ossl_asn1_get_value(obj);
|
564
|
+
switch(tag){
|
565
|
+
case V_ASN1_BOOLEAN:
|
566
|
+
ptr = (void*)(VALUE)obj_to_asn1bool(value);
|
567
|
+
free_func = NULL;
|
568
|
+
break;
|
569
|
+
case V_ASN1_INTEGER: /* FALLTHROUGH */
|
570
|
+
case V_ASN1_ENUMERATED:
|
571
|
+
ptr = obj_to_asn1int(value);
|
572
|
+
free_func = ASN1_INTEGER_free;
|
573
|
+
break;
|
574
|
+
case V_ASN1_BIT_STRING:
|
575
|
+
rflag = rb_attr_get(obj, sivUNUSED_BITS);
|
576
|
+
flag = NIL_P(rflag) ? -1 : NUM2INT(rflag);
|
577
|
+
ptr = obj_to_asn1bstr(value, flag);
|
578
|
+
free_func = ASN1_BIT_STRING_free;
|
579
|
+
break;
|
580
|
+
case V_ASN1_NULL:
|
581
|
+
ptr = obj_to_asn1null(value);
|
582
|
+
free_func = ASN1_NULL_free;
|
583
|
+
break;
|
584
|
+
case V_ASN1_OCTET_STRING: /* FALLTHROUGH */
|
585
|
+
case V_ASN1_UTF8STRING: /* FALLTHROUGH */
|
586
|
+
case V_ASN1_NUMERICSTRING: /* FALLTHROUGH */
|
587
|
+
case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */
|
588
|
+
case V_ASN1_T61STRING: /* FALLTHROUGH */
|
589
|
+
case V_ASN1_VIDEOTEXSTRING: /* FALLTHROUGH */
|
590
|
+
case V_ASN1_IA5STRING: /* FALLTHROUGH */
|
591
|
+
case V_ASN1_GRAPHICSTRING: /* FALLTHROUGH */
|
592
|
+
case V_ASN1_ISO64STRING: /* FALLTHROUGH */
|
593
|
+
case V_ASN1_GENERALSTRING: /* FALLTHROUGH */
|
594
|
+
case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
|
595
|
+
case V_ASN1_BMPSTRING:
|
596
|
+
ptr = obj_to_asn1str(value);
|
597
|
+
free_func = ASN1_STRING_free;
|
598
|
+
break;
|
599
|
+
case V_ASN1_OBJECT:
|
600
|
+
ptr = obj_to_asn1obj(value);
|
601
|
+
free_func = ASN1_OBJECT_free;
|
602
|
+
break;
|
603
|
+
case V_ASN1_UTCTIME:
|
604
|
+
ptr = obj_to_asn1utime(value);
|
605
|
+
free_func = ASN1_TIME_free;
|
606
|
+
break;
|
607
|
+
case V_ASN1_GENERALIZEDTIME:
|
608
|
+
ptr = obj_to_asn1gtime(value);
|
609
|
+
free_func = ASN1_TIME_free;
|
610
|
+
break;
|
611
|
+
case V_ASN1_SET: /* FALLTHROUGH */
|
612
|
+
case V_ASN1_SEQUENCE:
|
613
|
+
ptr = obj_to_asn1derstr(obj);
|
614
|
+
free_func = ASN1_STRING_free;
|
615
|
+
break;
|
616
|
+
default:
|
617
|
+
ossl_raise(eASN1Error, "unsupported ASN.1 type");
|
618
|
+
}
|
619
|
+
if(!(ret = OPENSSL_malloc(sizeof(ASN1_TYPE)))){
|
620
|
+
if(free_func) free_func(ptr);
|
621
|
+
ossl_raise(eASN1Error, "ASN1_TYPE alloc failure");
|
622
|
+
}
|
623
|
+
memset(ret, 0, sizeof(ASN1_TYPE));
|
624
|
+
ASN1_TYPE_set(ret, tag, ptr);
|
625
|
+
|
626
|
+
return ret;
|
627
|
+
}
|
628
|
+
|
629
|
+
static int
|
630
|
+
ossl_asn1_default_tag(VALUE obj)
|
631
|
+
{
|
632
|
+
VALUE tmp_class, tag;
|
633
|
+
|
634
|
+
tmp_class = CLASS_OF(obj);
|
635
|
+
while (tmp_class) {
|
636
|
+
tag = rb_hash_lookup(class_tag_map, tmp_class);
|
637
|
+
if (tag != Qnil) {
|
638
|
+
return NUM2INT(tag);
|
639
|
+
}
|
640
|
+
tmp_class = rb_class_superclass(tmp_class);
|
641
|
+
}
|
642
|
+
ossl_raise(eASN1Error, "universal tag for %"PRIsVALUE" not found",
|
643
|
+
rb_obj_class(obj));
|
644
|
+
|
645
|
+
return -1; /* dummy */
|
646
|
+
}
|
647
|
+
|
648
|
+
static int
|
649
|
+
ossl_asn1_tag(VALUE obj)
|
650
|
+
{
|
651
|
+
VALUE tag;
|
652
|
+
|
653
|
+
tag = ossl_asn1_get_tag(obj);
|
654
|
+
if(NIL_P(tag))
|
655
|
+
ossl_raise(eASN1Error, "tag number not specified");
|
656
|
+
|
657
|
+
return NUM2INT(tag);
|
658
|
+
}
|
659
|
+
|
660
|
+
static int
|
661
|
+
ossl_asn1_is_explicit(VALUE obj)
|
662
|
+
{
|
663
|
+
VALUE s;
|
664
|
+
int ret = -1;
|
665
|
+
|
666
|
+
s = ossl_asn1_get_tagging(obj);
|
667
|
+
if(NIL_P(s)) return 0;
|
668
|
+
else if(SYMBOL_P(s)){
|
669
|
+
if (SYM2ID(s) == sIMPLICIT)
|
670
|
+
ret = 0;
|
671
|
+
else if (SYM2ID(s) == sEXPLICIT)
|
672
|
+
ret = 1;
|
673
|
+
}
|
674
|
+
if(ret < 0){
|
675
|
+
ossl_raise(eASN1Error, "invalid tag default");
|
676
|
+
}
|
677
|
+
|
678
|
+
return ret;
|
679
|
+
}
|
680
|
+
|
681
|
+
static int
|
682
|
+
ossl_asn1_tag_class(VALUE obj)
|
683
|
+
{
|
684
|
+
VALUE s;
|
685
|
+
int ret = -1;
|
686
|
+
|
687
|
+
s = ossl_asn1_get_tag_class(obj);
|
688
|
+
if(NIL_P(s)) ret = V_ASN1_UNIVERSAL;
|
689
|
+
else if(SYMBOL_P(s)){
|
690
|
+
if (SYM2ID(s) == sUNIVERSAL)
|
691
|
+
ret = V_ASN1_UNIVERSAL;
|
692
|
+
else if (SYM2ID(s) == sAPPLICATION)
|
693
|
+
ret = V_ASN1_APPLICATION;
|
694
|
+
else if (SYM2ID(s) == sCONTEXT_SPECIFIC)
|
695
|
+
ret = V_ASN1_CONTEXT_SPECIFIC;
|
696
|
+
else if (SYM2ID(s) == sPRIVATE)
|
697
|
+
ret = V_ASN1_PRIVATE;
|
698
|
+
}
|
699
|
+
if(ret < 0){
|
700
|
+
ossl_raise(eASN1Error, "invalid tag class");
|
701
|
+
}
|
702
|
+
|
703
|
+
return ret;
|
704
|
+
}
|
705
|
+
|
706
|
+
static VALUE
|
707
|
+
ossl_asn1_class2sym(int tc)
|
708
|
+
{
|
709
|
+
if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
|
710
|
+
return ID2SYM(sPRIVATE);
|
711
|
+
else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
|
712
|
+
return ID2SYM(sCONTEXT_SPECIFIC);
|
713
|
+
else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
|
714
|
+
return ID2SYM(sAPPLICATION);
|
715
|
+
else
|
716
|
+
return ID2SYM(sUNIVERSAL);
|
717
|
+
}
|
718
|
+
|
719
|
+
/*
|
720
|
+
* call-seq:
|
721
|
+
* OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data
|
722
|
+
*
|
723
|
+
* +value+: Please have a look at Constructive and Primitive to see how Ruby
|
724
|
+
* types are mapped to ASN.1 types and vice versa.
|
725
|
+
*
|
726
|
+
* +tag+: A +Number+ indicating the tag number.
|
727
|
+
*
|
728
|
+
* +tag_class+: A +Symbol+ indicating the tag class. Please cf. ASN1 for
|
729
|
+
* possible values.
|
730
|
+
*
|
731
|
+
* == Example
|
732
|
+
* asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42)
|
733
|
+
* tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER
|
734
|
+
*/
|
735
|
+
static VALUE
|
736
|
+
ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
|
737
|
+
{
|
738
|
+
if(!SYMBOL_P(tag_class))
|
739
|
+
ossl_raise(eASN1Error, "invalid tag class");
|
740
|
+
if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31)
|
741
|
+
ossl_raise(eASN1Error, "tag number for Universal too large");
|
742
|
+
ossl_asn1_set_tag(self, tag);
|
743
|
+
ossl_asn1_set_value(self, value);
|
744
|
+
ossl_asn1_set_tag_class(self, tag_class);
|
745
|
+
ossl_asn1_set_infinite_length(self, Qfalse);
|
746
|
+
|
747
|
+
return self;
|
748
|
+
}
|
749
|
+
|
750
|
+
static VALUE
|
751
|
+
join_der_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, str))
|
752
|
+
{
|
753
|
+
i = ossl_to_der_if_possible(i);
|
754
|
+
StringValue(i);
|
755
|
+
rb_str_append(str, i);
|
756
|
+
return Qnil;
|
757
|
+
}
|
758
|
+
|
759
|
+
static VALUE
|
760
|
+
join_der(VALUE enumerable)
|
761
|
+
{
|
762
|
+
VALUE str = rb_str_new(0, 0);
|
763
|
+
rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str);
|
764
|
+
return str;
|
765
|
+
}
|
766
|
+
|
767
|
+
/*
|
768
|
+
* call-seq:
|
769
|
+
* asn1.to_der => DER-encoded String
|
770
|
+
*
|
771
|
+
* Encodes this ASN1Data into a DER-encoded String value. The result is
|
772
|
+
* DER-encoded except for the possibility of infinite length encodings.
|
773
|
+
* Infinite length encodings are not allowed in strict DER, so strictly
|
774
|
+
* speaking the result of such an encoding would be a BER-encoding.
|
775
|
+
*/
|
776
|
+
static VALUE
|
777
|
+
ossl_asn1data_to_der(VALUE self)
|
778
|
+
{
|
779
|
+
VALUE value, der, inf_length;
|
780
|
+
int tag, tag_class, is_cons = 0;
|
781
|
+
long length;
|
782
|
+
unsigned char *p;
|
783
|
+
|
784
|
+
value = ossl_asn1_get_value(self);
|
785
|
+
if(rb_obj_is_kind_of(value, rb_cArray)){
|
786
|
+
is_cons = 1;
|
787
|
+
value = join_der(value);
|
788
|
+
}
|
789
|
+
StringValue(value);
|
790
|
+
|
791
|
+
tag = ossl_asn1_tag(self);
|
792
|
+
tag_class = ossl_asn1_tag_class(self);
|
793
|
+
inf_length = ossl_asn1_get_infinite_length(self);
|
794
|
+
if (inf_length == Qtrue) {
|
795
|
+
is_cons = 2;
|
796
|
+
}
|
797
|
+
if((length = ASN1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0)
|
798
|
+
ossl_raise(eASN1Error, NULL);
|
799
|
+
der = rb_str_new(0, length);
|
800
|
+
p = (unsigned char *)RSTRING_PTR(der);
|
801
|
+
ASN1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class);
|
802
|
+
memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
|
803
|
+
p += RSTRING_LEN(value);
|
804
|
+
ossl_str_adjust(der, p);
|
805
|
+
|
806
|
+
return der;
|
807
|
+
}
|
808
|
+
|
809
|
+
static VALUE
|
810
|
+
int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
|
811
|
+
VALUE tc, long *num_read)
|
812
|
+
{
|
813
|
+
VALUE value, asn1data;
|
814
|
+
unsigned char *p;
|
815
|
+
long flag = 0;
|
816
|
+
|
817
|
+
p = *pp;
|
818
|
+
|
819
|
+
if(tc == sUNIVERSAL && tag < ossl_asn1_info_size) {
|
820
|
+
switch(tag){
|
821
|
+
case V_ASN1_EOC:
|
822
|
+
value = decode_eoc(p, hlen+length);
|
823
|
+
break;
|
824
|
+
case V_ASN1_BOOLEAN:
|
825
|
+
value = decode_bool(p, hlen+length);
|
826
|
+
break;
|
827
|
+
case V_ASN1_INTEGER:
|
828
|
+
value = decode_int(p, hlen+length);
|
829
|
+
break;
|
830
|
+
case V_ASN1_BIT_STRING:
|
831
|
+
value = decode_bstr(p, hlen+length, &flag);
|
832
|
+
break;
|
833
|
+
case V_ASN1_NULL:
|
834
|
+
value = decode_null(p, hlen+length);
|
835
|
+
break;
|
836
|
+
case V_ASN1_ENUMERATED:
|
837
|
+
value = decode_enum(p, hlen+length);
|
838
|
+
break;
|
839
|
+
case V_ASN1_OBJECT:
|
840
|
+
value = decode_obj(p, hlen+length);
|
841
|
+
break;
|
842
|
+
case V_ASN1_UTCTIME: /* FALLTHROUGH */
|
843
|
+
case V_ASN1_GENERALIZEDTIME:
|
844
|
+
value = decode_time(p, hlen+length);
|
845
|
+
break;
|
846
|
+
default:
|
847
|
+
/* use original value */
|
848
|
+
p += hlen;
|
849
|
+
value = rb_str_new((const char *)p, length);
|
850
|
+
break;
|
851
|
+
}
|
852
|
+
}
|
853
|
+
else {
|
854
|
+
p += hlen;
|
855
|
+
value = rb_str_new((const char *)p, length);
|
856
|
+
}
|
857
|
+
|
858
|
+
*pp += hlen + length;
|
859
|
+
*num_read = hlen + length;
|
860
|
+
|
861
|
+
if (tc == sUNIVERSAL && tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
|
862
|
+
VALUE klass = *ossl_asn1_info[tag].klass;
|
863
|
+
VALUE args[4];
|
864
|
+
args[0] = value;
|
865
|
+
args[1] = INT2NUM(tag);
|
866
|
+
args[2] = Qnil;
|
867
|
+
args[3] = ID2SYM(tc);
|
868
|
+
asn1data = rb_obj_alloc(klass);
|
869
|
+
ossl_asn1_initialize(4, args, asn1data);
|
870
|
+
if(tag == V_ASN1_BIT_STRING){
|
871
|
+
rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag));
|
872
|
+
}
|
873
|
+
}
|
874
|
+
else {
|
875
|
+
asn1data = rb_obj_alloc(cASN1Data);
|
876
|
+
ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), ID2SYM(tc));
|
877
|
+
}
|
878
|
+
|
879
|
+
return asn1data;
|
880
|
+
}
|
881
|
+
|
882
|
+
static VALUE
|
883
|
+
int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
|
884
|
+
long *offset, int depth, int yield, int j,
|
885
|
+
int tag, VALUE tc, long *num_read)
|
886
|
+
{
|
887
|
+
VALUE value, asn1data, ary;
|
888
|
+
int infinite;
|
889
|
+
long off = *offset;
|
890
|
+
|
891
|
+
infinite = (j == 0x21);
|
892
|
+
ary = rb_ary_new();
|
893
|
+
|
894
|
+
while (length > 0 || infinite) {
|
895
|
+
long inner_read = 0;
|
896
|
+
value = ossl_asn1_decode0(pp, max_len, &off, depth + 1, yield, &inner_read);
|
897
|
+
*num_read += inner_read;
|
898
|
+
max_len -= inner_read;
|
899
|
+
rb_ary_push(ary, value);
|
900
|
+
if (length > 0)
|
901
|
+
length -= inner_read;
|
902
|
+
|
903
|
+
if (infinite &&
|
904
|
+
NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC &&
|
905
|
+
SYM2ID(ossl_asn1_get_tag_class(value)) == sUNIVERSAL) {
|
906
|
+
break;
|
907
|
+
}
|
908
|
+
}
|
909
|
+
|
910
|
+
if (tc == sUNIVERSAL) {
|
911
|
+
VALUE args[4];
|
912
|
+
int not_sequence_or_set;
|
913
|
+
|
914
|
+
not_sequence_or_set = tag != V_ASN1_SEQUENCE && tag != V_ASN1_SET;
|
915
|
+
|
916
|
+
if (not_sequence_or_set) {
|
917
|
+
if (infinite) {
|
918
|
+
asn1data = rb_obj_alloc(cASN1Constructive);
|
919
|
+
}
|
920
|
+
else {
|
921
|
+
ossl_raise(eASN1Error, "invalid non-infinite tag");
|
922
|
+
return Qnil;
|
923
|
+
}
|
924
|
+
}
|
925
|
+
else {
|
926
|
+
VALUE klass = *ossl_asn1_info[tag].klass;
|
927
|
+
asn1data = rb_obj_alloc(klass);
|
928
|
+
}
|
929
|
+
args[0] = ary;
|
930
|
+
args[1] = INT2NUM(tag);
|
931
|
+
args[2] = Qnil;
|
932
|
+
args[3] = ID2SYM(tc);
|
933
|
+
ossl_asn1_initialize(4, args, asn1data);
|
934
|
+
}
|
935
|
+
else {
|
936
|
+
asn1data = rb_obj_alloc(cASN1Data);
|
937
|
+
ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), ID2SYM(tc));
|
938
|
+
}
|
939
|
+
|
940
|
+
if (infinite)
|
941
|
+
ossl_asn1_set_infinite_length(asn1data, Qtrue);
|
942
|
+
else
|
943
|
+
ossl_asn1_set_infinite_length(asn1data, Qfalse);
|
944
|
+
|
945
|
+
*offset = off;
|
946
|
+
return asn1data;
|
947
|
+
}
|
948
|
+
|
949
|
+
static VALUE
|
950
|
+
ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
|
951
|
+
int yield, long *num_read)
|
952
|
+
{
|
953
|
+
unsigned char *start, *p;
|
954
|
+
const unsigned char *p0;
|
955
|
+
long len = 0, inner_read = 0, off = *offset, hlen;
|
956
|
+
int tag, tc, j;
|
957
|
+
VALUE asn1data, tag_class;
|
958
|
+
|
959
|
+
p = *pp;
|
960
|
+
start = p;
|
961
|
+
p0 = p;
|
962
|
+
j = ASN1_get_object(&p0, &len, &tag, &tc, length);
|
963
|
+
p = (unsigned char *)p0;
|
964
|
+
if(j & 0x80) ossl_raise(eASN1Error, NULL);
|
965
|
+
if(len > length) ossl_raise(eASN1Error, "value is too short");
|
966
|
+
if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
|
967
|
+
tag_class = sPRIVATE;
|
968
|
+
else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
|
969
|
+
tag_class = sCONTEXT_SPECIFIC;
|
970
|
+
else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
|
971
|
+
tag_class = sAPPLICATION;
|
972
|
+
else
|
973
|
+
tag_class = sUNIVERSAL;
|
974
|
+
|
975
|
+
hlen = p - start;
|
976
|
+
|
977
|
+
if(yield) {
|
978
|
+
VALUE arg = rb_ary_new();
|
979
|
+
rb_ary_push(arg, LONG2NUM(depth));
|
980
|
+
rb_ary_push(arg, LONG2NUM(*offset));
|
981
|
+
rb_ary_push(arg, LONG2NUM(hlen));
|
982
|
+
rb_ary_push(arg, LONG2NUM(len));
|
983
|
+
rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
|
984
|
+
rb_ary_push(arg, ossl_asn1_class2sym(tc));
|
985
|
+
rb_ary_push(arg, INT2NUM(tag));
|
986
|
+
rb_yield(arg);
|
987
|
+
}
|
988
|
+
|
989
|
+
if(j & V_ASN1_CONSTRUCTED) {
|
990
|
+
*pp += hlen;
|
991
|
+
off += hlen;
|
992
|
+
asn1data = int_ossl_asn1_decode0_cons(pp, length, len, &off, depth, yield, j, tag, tag_class, &inner_read);
|
993
|
+
inner_read += hlen;
|
994
|
+
}
|
995
|
+
else {
|
996
|
+
if ((j & 0x01) && (len == 0)) ossl_raise(eASN1Error, "Infinite length for primitive value");
|
997
|
+
asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read);
|
998
|
+
off += hlen + len;
|
999
|
+
}
|
1000
|
+
if (num_read)
|
1001
|
+
*num_read = inner_read;
|
1002
|
+
if (len != 0 && inner_read != hlen + len) {
|
1003
|
+
ossl_raise(eASN1Error,
|
1004
|
+
"Type mismatch. Bytes read: %ld Bytes available: %ld",
|
1005
|
+
inner_read, hlen + len);
|
1006
|
+
}
|
1007
|
+
|
1008
|
+
*offset = off;
|
1009
|
+
return asn1data;
|
1010
|
+
}
|
1011
|
+
|
1012
|
+
static void
|
1013
|
+
int_ossl_decode_sanity_check(long len, long read, long offset)
|
1014
|
+
{
|
1015
|
+
if (len != 0 && (read != len || offset != len)) {
|
1016
|
+
ossl_raise(eASN1Error,
|
1017
|
+
"Type mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ld",
|
1018
|
+
read, len, offset);
|
1019
|
+
}
|
1020
|
+
}
|
1021
|
+
|
1022
|
+
/*
|
1023
|
+
* call-seq:
|
1024
|
+
* OpenSSL::ASN1.traverse(asn1) -> nil
|
1025
|
+
*
|
1026
|
+
* If a block is given, it prints out each of the elements encountered.
|
1027
|
+
* Block parameters are (in that order):
|
1028
|
+
* * depth: The recursion depth, plus one with each constructed value being encountered (Number)
|
1029
|
+
* * offset: Current byte offset (Number)
|
1030
|
+
* * header length: Combined length in bytes of the Tag and Length headers. (Number)
|
1031
|
+
* * length: The overall remaining length of the entire data (Number)
|
1032
|
+
* * constructed: Whether this value is constructed or not (Boolean)
|
1033
|
+
* * tag_class: Current tag class (Symbol)
|
1034
|
+
* * tag: The current tag (Number)
|
1035
|
+
*
|
1036
|
+
* == Example
|
1037
|
+
* der = File.binread('asn1data.der')
|
1038
|
+
* OpenSSL::ASN1.traverse(der) do | depth, offset, header_len, length, constructed, tag_class, tag|
|
1039
|
+
* puts "Depth: #{depth} Offset: #{offset} Length: #{length}"
|
1040
|
+
* puts "Header length: #{header_len} Tag: #{tag} Tag class: #{tag_class} Constructed: #{constructed}"
|
1041
|
+
* end
|
1042
|
+
*/
|
1043
|
+
static VALUE
|
1044
|
+
ossl_asn1_traverse(VALUE self, VALUE obj)
|
1045
|
+
{
|
1046
|
+
unsigned char *p;
|
1047
|
+
VALUE tmp;
|
1048
|
+
long len, read = 0, offset = 0;
|
1049
|
+
|
1050
|
+
obj = ossl_to_der_if_possible(obj);
|
1051
|
+
tmp = rb_str_new4(StringValue(obj));
|
1052
|
+
p = (unsigned char *)RSTRING_PTR(tmp);
|
1053
|
+
len = RSTRING_LEN(tmp);
|
1054
|
+
ossl_asn1_decode0(&p, len, &offset, 0, 1, &read);
|
1055
|
+
RB_GC_GUARD(tmp);
|
1056
|
+
int_ossl_decode_sanity_check(len, read, offset);
|
1057
|
+
return Qnil;
|
1058
|
+
}
|
1059
|
+
|
1060
|
+
/*
|
1061
|
+
* call-seq:
|
1062
|
+
* OpenSSL::ASN1.decode(der) -> ASN1Data
|
1063
|
+
*
|
1064
|
+
* Decodes a BER- or DER-encoded value and creates an ASN1Data instance. +der+
|
1065
|
+
* may be a +String+ or any object that features a +#to_der+ method transforming
|
1066
|
+
* it into a BER-/DER-encoded +String+.
|
1067
|
+
*
|
1068
|
+
* == Example
|
1069
|
+
* der = File.binread('asn1data')
|
1070
|
+
* asn1 = OpenSSL::ASN1.decode(der)
|
1071
|
+
*/
|
1072
|
+
static VALUE
|
1073
|
+
ossl_asn1_decode(VALUE self, VALUE obj)
|
1074
|
+
{
|
1075
|
+
VALUE ret;
|
1076
|
+
unsigned char *p;
|
1077
|
+
VALUE tmp;
|
1078
|
+
long len, read = 0, offset = 0;
|
1079
|
+
|
1080
|
+
obj = ossl_to_der_if_possible(obj);
|
1081
|
+
tmp = rb_str_new4(StringValue(obj));
|
1082
|
+
p = (unsigned char *)RSTRING_PTR(tmp);
|
1083
|
+
len = RSTRING_LEN(tmp);
|
1084
|
+
ret = ossl_asn1_decode0(&p, len, &offset, 0, 0, &read);
|
1085
|
+
RB_GC_GUARD(tmp);
|
1086
|
+
int_ossl_decode_sanity_check(len, read, offset);
|
1087
|
+
return ret;
|
1088
|
+
}
|
1089
|
+
|
1090
|
+
/*
|
1091
|
+
* call-seq:
|
1092
|
+
* OpenSSL::ASN1.decode_all(der) -> Array of ASN1Data
|
1093
|
+
*
|
1094
|
+
* Similar to +decode+ with the difference that +decode+ expects one
|
1095
|
+
* distinct value represented in +der+. +decode_all+ on the contrary
|
1096
|
+
* decodes a sequence of sequential BER/DER values lined up in +der+
|
1097
|
+
* and returns them as an array.
|
1098
|
+
*
|
1099
|
+
* == Example
|
1100
|
+
* ders = File.binread('asn1data_seq')
|
1101
|
+
* asn1_ary = OpenSSL::ASN1.decode_all(ders)
|
1102
|
+
*/
|
1103
|
+
static VALUE
|
1104
|
+
ossl_asn1_decode_all(VALUE self, VALUE obj)
|
1105
|
+
{
|
1106
|
+
VALUE ary, val;
|
1107
|
+
unsigned char *p;
|
1108
|
+
long len, tmp_len = 0, read = 0, offset = 0;
|
1109
|
+
VALUE tmp;
|
1110
|
+
|
1111
|
+
obj = ossl_to_der_if_possible(obj);
|
1112
|
+
tmp = rb_str_new4(StringValue(obj));
|
1113
|
+
p = (unsigned char *)RSTRING_PTR(tmp);
|
1114
|
+
len = RSTRING_LEN(tmp);
|
1115
|
+
tmp_len = len;
|
1116
|
+
ary = rb_ary_new();
|
1117
|
+
while (tmp_len > 0) {
|
1118
|
+
long tmp_read = 0;
|
1119
|
+
val = ossl_asn1_decode0(&p, tmp_len, &offset, 0, 0, &tmp_read);
|
1120
|
+
rb_ary_push(ary, val);
|
1121
|
+
read += tmp_read;
|
1122
|
+
tmp_len -= tmp_read;
|
1123
|
+
}
|
1124
|
+
RB_GC_GUARD(tmp);
|
1125
|
+
int_ossl_decode_sanity_check(len, read, offset);
|
1126
|
+
return ary;
|
1127
|
+
}
|
1128
|
+
|
1129
|
+
/*
|
1130
|
+
* call-seq:
|
1131
|
+
* OpenSSL::ASN1::Primitive.new( value [, tag, tagging, tag_class ]) => Primitive
|
1132
|
+
*
|
1133
|
+
* +value+: is mandatory.
|
1134
|
+
*
|
1135
|
+
* +tag+: optional, may be specified for tagged values. If no +tag+ is
|
1136
|
+
* specified, the UNIVERSAL tag corresponding to the Primitive sub-class
|
1137
|
+
* is used by default.
|
1138
|
+
*
|
1139
|
+
* +tagging+: may be used as an encoding hint to encode a value either
|
1140
|
+
* explicitly or implicitly, see ASN1 for possible values.
|
1141
|
+
*
|
1142
|
+
* +tag_class+: if +tag+ and +tagging+ are +nil+ then this is set to
|
1143
|
+
* +:UNIVERSAL+ by default. If either +tag+ or +tagging+ are set then
|
1144
|
+
* +:CONTEXT_SPECIFIC+ is used as the default. For possible values please
|
1145
|
+
* cf. ASN1.
|
1146
|
+
*
|
1147
|
+
* == Example
|
1148
|
+
* int = OpenSSL::ASN1::Integer.new(42)
|
1149
|
+
* zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :IMPLICIT)
|
1150
|
+
* private_explicit_zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :EXPLICIT, :PRIVATE)
|
1151
|
+
*/
|
1152
|
+
static VALUE
|
1153
|
+
ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
|
1154
|
+
{
|
1155
|
+
VALUE value, tag, tagging, tag_class;
|
1156
|
+
|
1157
|
+
rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class);
|
1158
|
+
if(argc > 1){
|
1159
|
+
if(NIL_P(tag))
|
1160
|
+
ossl_raise(eASN1Error, "must specify tag number");
|
1161
|
+
if(!NIL_P(tagging) && !SYMBOL_P(tagging))
|
1162
|
+
ossl_raise(eASN1Error, "invalid tagging method");
|
1163
|
+
if(NIL_P(tag_class)) {
|
1164
|
+
if (NIL_P(tagging))
|
1165
|
+
tag_class = ID2SYM(sUNIVERSAL);
|
1166
|
+
else
|
1167
|
+
tag_class = ID2SYM(sCONTEXT_SPECIFIC);
|
1168
|
+
}
|
1169
|
+
if(!SYMBOL_P(tag_class))
|
1170
|
+
ossl_raise(eASN1Error, "invalid tag class");
|
1171
|
+
if(!NIL_P(tagging) && SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
|
1172
|
+
ossl_raise(eASN1Error, "tag number for Universal too large");
|
1173
|
+
}
|
1174
|
+
else{
|
1175
|
+
tag = INT2NUM(ossl_asn1_default_tag(self));
|
1176
|
+
tagging = Qnil;
|
1177
|
+
tag_class = ID2SYM(sUNIVERSAL);
|
1178
|
+
}
|
1179
|
+
ossl_asn1_set_tag(self, tag);
|
1180
|
+
ossl_asn1_set_value(self, value);
|
1181
|
+
ossl_asn1_set_tagging(self, tagging);
|
1182
|
+
ossl_asn1_set_tag_class(self, tag_class);
|
1183
|
+
ossl_asn1_set_infinite_length(self, Qfalse);
|
1184
|
+
|
1185
|
+
return self;
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
static VALUE
|
1189
|
+
ossl_asn1eoc_initialize(VALUE self) {
|
1190
|
+
VALUE tag, tagging, tag_class, value;
|
1191
|
+
tag = INT2NUM(ossl_asn1_default_tag(self));
|
1192
|
+
tagging = Qnil;
|
1193
|
+
tag_class = ID2SYM(sUNIVERSAL);
|
1194
|
+
value = rb_str_new("", 0);
|
1195
|
+
ossl_asn1_set_tag(self, tag);
|
1196
|
+
ossl_asn1_set_value(self, value);
|
1197
|
+
ossl_asn1_set_tagging(self, tagging);
|
1198
|
+
ossl_asn1_set_tag_class(self, tag_class);
|
1199
|
+
ossl_asn1_set_infinite_length(self, Qfalse);
|
1200
|
+
return self;
|
1201
|
+
}
|
1202
|
+
|
1203
|
+
/*
|
1204
|
+
* call-seq:
|
1205
|
+
* asn1.to_der => DER-encoded String
|
1206
|
+
*
|
1207
|
+
* See ASN1Data#to_der for details. *
|
1208
|
+
*/
|
1209
|
+
static VALUE
|
1210
|
+
ossl_asn1prim_to_der(VALUE self)
|
1211
|
+
{
|
1212
|
+
ASN1_TYPE *asn1;
|
1213
|
+
int tn, tc, explicit;
|
1214
|
+
long len, reallen;
|
1215
|
+
unsigned char *buf, *p;
|
1216
|
+
VALUE str;
|
1217
|
+
|
1218
|
+
tn = NUM2INT(ossl_asn1_get_tag(self));
|
1219
|
+
tc = ossl_asn1_tag_class(self);
|
1220
|
+
explicit = ossl_asn1_is_explicit(self);
|
1221
|
+
asn1 = ossl_asn1_get_asn1type(self);
|
1222
|
+
|
1223
|
+
len = ASN1_object_size(1, i2d_ASN1_TYPE(asn1, NULL), tn);
|
1224
|
+
if(!(buf = OPENSSL_malloc(len))){
|
1225
|
+
ASN1_TYPE_free(asn1);
|
1226
|
+
ossl_raise(eASN1Error, "cannot alloc buffer");
|
1227
|
+
}
|
1228
|
+
p = buf;
|
1229
|
+
if (tc == V_ASN1_UNIVERSAL) {
|
1230
|
+
i2d_ASN1_TYPE(asn1, &p);
|
1231
|
+
} else if (explicit) {
|
1232
|
+
ASN1_put_object(&p, 1, i2d_ASN1_TYPE(asn1, NULL), tn, tc);
|
1233
|
+
i2d_ASN1_TYPE(asn1, &p);
|
1234
|
+
} else {
|
1235
|
+
i2d_ASN1_TYPE(asn1, &p);
|
1236
|
+
*buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED);
|
1237
|
+
}
|
1238
|
+
ASN1_TYPE_free(asn1);
|
1239
|
+
reallen = p - buf;
|
1240
|
+
assert(reallen <= len);
|
1241
|
+
str = ossl_buf2str((char *)buf, rb_long2int(reallen)); /* buf will be free in ossl_buf2str */
|
1242
|
+
|
1243
|
+
return str;
|
1244
|
+
}
|
1245
|
+
|
1246
|
+
/*
|
1247
|
+
* call-seq:
|
1248
|
+
* asn1.to_der => DER-encoded String
|
1249
|
+
*
|
1250
|
+
* See ASN1Data#to_der for details.
|
1251
|
+
*/
|
1252
|
+
static VALUE
|
1253
|
+
ossl_asn1cons_to_der(VALUE self)
|
1254
|
+
{
|
1255
|
+
int tag, tn, tc, explicit, constructed = 1;
|
1256
|
+
int found_prim = 0, seq_len;
|
1257
|
+
long length;
|
1258
|
+
unsigned char *p;
|
1259
|
+
VALUE value, str, inf_length;
|
1260
|
+
|
1261
|
+
tn = NUM2INT(ossl_asn1_get_tag(self));
|
1262
|
+
tc = ossl_asn1_tag_class(self);
|
1263
|
+
inf_length = ossl_asn1_get_infinite_length(self);
|
1264
|
+
if (inf_length == Qtrue) {
|
1265
|
+
VALUE ary, example;
|
1266
|
+
constructed = 2;
|
1267
|
+
if (CLASS_OF(self) == cASN1Sequence ||
|
1268
|
+
CLASS_OF(self) == cASN1Set) {
|
1269
|
+
tag = ossl_asn1_default_tag(self);
|
1270
|
+
}
|
1271
|
+
else { /* must be a constructive encoding of a primitive value */
|
1272
|
+
ary = ossl_asn1_get_value(self);
|
1273
|
+
if (!rb_obj_is_kind_of(ary, rb_cArray))
|
1274
|
+
ossl_raise(eASN1Error, "Constructive value must be an Array");
|
1275
|
+
/* Recursively descend until a primitive value is found.
|
1276
|
+
The overall value of the entire constructed encoding
|
1277
|
+
is of the type of the first primitive encoding to be
|
1278
|
+
found. */
|
1279
|
+
while (!found_prim){
|
1280
|
+
example = rb_ary_entry(ary, 0);
|
1281
|
+
if (rb_obj_is_kind_of(example, cASN1Primitive)){
|
1282
|
+
found_prim = 1;
|
1283
|
+
}
|
1284
|
+
else {
|
1285
|
+
/* example is another ASN1Constructive */
|
1286
|
+
if (!rb_obj_is_kind_of(example, cASN1Constructive)){
|
1287
|
+
ossl_raise(eASN1Error, "invalid constructed encoding");
|
1288
|
+
return Qnil; /* dummy */
|
1289
|
+
}
|
1290
|
+
ary = ossl_asn1_get_value(example);
|
1291
|
+
}
|
1292
|
+
}
|
1293
|
+
tag = ossl_asn1_default_tag(example);
|
1294
|
+
}
|
1295
|
+
}
|
1296
|
+
else {
|
1297
|
+
if (CLASS_OF(self) == cASN1Constructive)
|
1298
|
+
ossl_raise(eASN1Error, "Constructive shall only be used with infinite length");
|
1299
|
+
tag = ossl_asn1_default_tag(self);
|
1300
|
+
}
|
1301
|
+
explicit = ossl_asn1_is_explicit(self);
|
1302
|
+
value = join_der(ossl_asn1_get_value(self));
|
1303
|
+
|
1304
|
+
seq_len = ASN1_object_size(constructed, RSTRING_LENINT(value), tag);
|
1305
|
+
length = ASN1_object_size(constructed, seq_len, tn);
|
1306
|
+
str = rb_str_new(0, length);
|
1307
|
+
p = (unsigned char *)RSTRING_PTR(str);
|
1308
|
+
if(tc == V_ASN1_UNIVERSAL)
|
1309
|
+
ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
|
1310
|
+
else{
|
1311
|
+
if(explicit){
|
1312
|
+
ASN1_put_object(&p, constructed, seq_len, tn, tc);
|
1313
|
+
ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL);
|
1314
|
+
}
|
1315
|
+
else{
|
1316
|
+
ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
|
1317
|
+
}
|
1318
|
+
}
|
1319
|
+
memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
|
1320
|
+
p += RSTRING_LEN(value);
|
1321
|
+
|
1322
|
+
/* In this case we need an additional EOC (one for the explicit part and
|
1323
|
+
* one for the Constructive itself. The EOC for the Constructive is
|
1324
|
+
* supplied by the user, but that for the "explicit wrapper" must be
|
1325
|
+
* added here.
|
1326
|
+
*/
|
1327
|
+
if (explicit && inf_length == Qtrue) {
|
1328
|
+
ASN1_put_eoc(&p);
|
1329
|
+
}
|
1330
|
+
ossl_str_adjust(str, p);
|
1331
|
+
|
1332
|
+
return str;
|
1333
|
+
}
|
1334
|
+
|
1335
|
+
/*
|
1336
|
+
* call-seq:
|
1337
|
+
* asn1_ary.each { |asn1| block } => asn1_ary
|
1338
|
+
*
|
1339
|
+
* Calls <i>block</i> once for each element in +self+, passing that element
|
1340
|
+
* as parameter +asn1+. If no block is given, an enumerator is returned
|
1341
|
+
* instead.
|
1342
|
+
*
|
1343
|
+
* == Example
|
1344
|
+
* asn1_ary.each do |asn1|
|
1345
|
+
* puts asn1
|
1346
|
+
* end
|
1347
|
+
*/
|
1348
|
+
static VALUE
|
1349
|
+
ossl_asn1cons_each(VALUE self)
|
1350
|
+
{
|
1351
|
+
rb_ary_each(ossl_asn1_get_value(self));
|
1352
|
+
return self;
|
1353
|
+
}
|
1354
|
+
|
1355
|
+
/*
|
1356
|
+
* call-seq:
|
1357
|
+
* OpenSSL::ASN1::ObjectId.register(object_id, short_name, long_name)
|
1358
|
+
*
|
1359
|
+
* This adds a new ObjectId to the internal tables. Where +object_id+ is the
|
1360
|
+
* numerical form, +short_name+ is the short name, and +long_name+ is the long
|
1361
|
+
* name.
|
1362
|
+
*
|
1363
|
+
* Returns +true+ if successful. Raises an OpenSSL::ASN1::ASN1Error if it fails.
|
1364
|
+
*
|
1365
|
+
*/
|
1366
|
+
static VALUE
|
1367
|
+
ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
|
1368
|
+
{
|
1369
|
+
StringValueCStr(oid);
|
1370
|
+
StringValueCStr(sn);
|
1371
|
+
StringValueCStr(ln);
|
1372
|
+
|
1373
|
+
if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
|
1374
|
+
ossl_raise(eASN1Error, NULL);
|
1375
|
+
|
1376
|
+
return Qtrue;
|
1377
|
+
}
|
1378
|
+
|
1379
|
+
/* Document-method: OpenSSL::ASN1::ObjectId#sn
|
1380
|
+
*
|
1381
|
+
* The short name of the ObjectId, as defined in <openssl/objects.h>.
|
1382
|
+
*/
|
1383
|
+
/* Document-method: OpenSSL::ASN1::ObjectId#short_name
|
1384
|
+
*
|
1385
|
+
* +short_name+ is an alias to +sn+
|
1386
|
+
*/
|
1387
|
+
static VALUE
|
1388
|
+
ossl_asn1obj_get_sn(VALUE self)
|
1389
|
+
{
|
1390
|
+
VALUE val, ret = Qnil;
|
1391
|
+
int nid;
|
1392
|
+
|
1393
|
+
val = ossl_asn1_get_value(self);
|
1394
|
+
if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef)
|
1395
|
+
ret = rb_str_new2(OBJ_nid2sn(nid));
|
1396
|
+
|
1397
|
+
return ret;
|
1398
|
+
}
|
1399
|
+
|
1400
|
+
/* Document-method: OpenSSL::ASN1::ObjectId#ln
|
1401
|
+
*
|
1402
|
+
* The long name of the ObjectId, as defined in <openssl/objects.h>.
|
1403
|
+
*/
|
1404
|
+
/* Document-method: OpenSSL::ASN1::ObjectId#long_name
|
1405
|
+
*
|
1406
|
+
* +long_name+ is an alias to +ln+
|
1407
|
+
*/
|
1408
|
+
static VALUE
|
1409
|
+
ossl_asn1obj_get_ln(VALUE self)
|
1410
|
+
{
|
1411
|
+
VALUE val, ret = Qnil;
|
1412
|
+
int nid;
|
1413
|
+
|
1414
|
+
val = ossl_asn1_get_value(self);
|
1415
|
+
if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef)
|
1416
|
+
ret = rb_str_new2(OBJ_nid2ln(nid));
|
1417
|
+
|
1418
|
+
return ret;
|
1419
|
+
}
|
1420
|
+
|
1421
|
+
/* Document-method: OpenSSL::ASN1::ObjectId#oid
|
1422
|
+
*
|
1423
|
+
* The object identifier as a +String+, e.g. "1.2.3.4.5"
|
1424
|
+
*/
|
1425
|
+
static VALUE
|
1426
|
+
ossl_asn1obj_get_oid(VALUE self)
|
1427
|
+
{
|
1428
|
+
VALUE val;
|
1429
|
+
ASN1_OBJECT *a1obj;
|
1430
|
+
char buf[128];
|
1431
|
+
|
1432
|
+
val = ossl_asn1_get_value(self);
|
1433
|
+
a1obj = obj_to_asn1obj(val);
|
1434
|
+
OBJ_obj2txt(buf, sizeof(buf), a1obj, 1);
|
1435
|
+
ASN1_OBJECT_free(a1obj);
|
1436
|
+
|
1437
|
+
return rb_str_new2(buf);
|
1438
|
+
}
|
1439
|
+
|
1440
|
+
#define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
|
1441
|
+
static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\
|
1442
|
+
{ return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); }
|
1443
|
+
|
1444
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(Boolean)
|
1445
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(Integer)
|
1446
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(Enumerated)
|
1447
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(BitString)
|
1448
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(OctetString)
|
1449
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(UTF8String)
|
1450
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(NumericString)
|
1451
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(PrintableString)
|
1452
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(T61String)
|
1453
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(VideotexString)
|
1454
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(IA5String)
|
1455
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(GraphicString)
|
1456
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(ISO64String)
|
1457
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralString)
|
1458
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(UniversalString)
|
1459
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(BMPString)
|
1460
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(Null)
|
1461
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(ObjectId)
|
1462
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime)
|
1463
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime)
|
1464
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence)
|
1465
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(Set)
|
1466
|
+
OSSL_ASN1_IMPL_FACTORY_METHOD(EndOfContent)
|
1467
|
+
|
1468
|
+
void
|
1469
|
+
Init_ossl_asn1(void)
|
1470
|
+
{
|
1471
|
+
VALUE ary;
|
1472
|
+
int i;
|
1473
|
+
|
1474
|
+
#if 0
|
1475
|
+
mOSSL = rb_define_module("OpenSSL");
|
1476
|
+
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
|
1477
|
+
#endif
|
1478
|
+
|
1479
|
+
sUNIVERSAL = rb_intern("UNIVERSAL");
|
1480
|
+
sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
|
1481
|
+
sAPPLICATION = rb_intern("APPLICATION");
|
1482
|
+
sPRIVATE = rb_intern("PRIVATE");
|
1483
|
+
sEXPLICIT = rb_intern("EXPLICIT");
|
1484
|
+
sIMPLICIT = rb_intern("IMPLICIT");
|
1485
|
+
|
1486
|
+
sivVALUE = rb_intern("@value");
|
1487
|
+
sivTAG = rb_intern("@tag");
|
1488
|
+
sivTAGGING = rb_intern("@tagging");
|
1489
|
+
sivTAG_CLASS = rb_intern("@tag_class");
|
1490
|
+
sivINFINITE_LENGTH = rb_intern("@infinite_length");
|
1491
|
+
sivUNUSED_BITS = rb_intern("@unused_bits");
|
1492
|
+
|
1493
|
+
/*
|
1494
|
+
* Document-module: OpenSSL::ASN1
|
1495
|
+
*
|
1496
|
+
* Abstract Syntax Notation One (or ASN.1) is a notation syntax to
|
1497
|
+
* describe data structures and is defined in ITU-T X.680. ASN.1 itself
|
1498
|
+
* does not mandate any encoding or parsing rules, but usually ASN.1 data
|
1499
|
+
* structures are encoded using the Distinguished Encoding Rules (DER) or
|
1500
|
+
* less often the Basic Encoding Rules (BER) described in ITU-T X.690. DER
|
1501
|
+
* and BER encodings are binary Tag-Length-Value (TLV) encodings that are
|
1502
|
+
* quite concise compared to other popular data description formats such
|
1503
|
+
* as XML, JSON etc.
|
1504
|
+
* ASN.1 data structures are very common in cryptographic applications,
|
1505
|
+
* e.g. X.509 public key certificates or certificate revocation lists
|
1506
|
+
* (CRLs) are all defined in ASN.1 and DER-encoded. ASN.1, DER and BER are
|
1507
|
+
* the building blocks of applied cryptography.
|
1508
|
+
* The ASN1 module provides the necessary classes that allow generation
|
1509
|
+
* of ASN.1 data structures and the methods to encode them using a DER
|
1510
|
+
* encoding. The decode method allows parsing arbitrary BER-/DER-encoded
|
1511
|
+
* data to a Ruby object that can then be modified and re-encoded at will.
|
1512
|
+
*
|
1513
|
+
* == ASN.1 class hierarchy
|
1514
|
+
*
|
1515
|
+
* The base class representing ASN.1 structures is ASN1Data. ASN1Data offers
|
1516
|
+
* attributes to read and set the +tag+, the +tag_class+ and finally the
|
1517
|
+
* +value+ of a particular ASN.1 item. Upon parsing, any tagged values
|
1518
|
+
* (implicit or explicit) will be represented by ASN1Data instances because
|
1519
|
+
* their "real type" can only be determined using out-of-band information
|
1520
|
+
* from the ASN.1 type declaration. Since this information is normally
|
1521
|
+
* known when encoding a type, all sub-classes of ASN1Data offer an
|
1522
|
+
* additional attribute +tagging+ that allows to encode a value implicitly
|
1523
|
+
* (+:IMPLICIT+) or explicitly (+:EXPLICIT+).
|
1524
|
+
*
|
1525
|
+
* === Constructive
|
1526
|
+
*
|
1527
|
+
* Constructive is, as its name implies, the base class for all
|
1528
|
+
* constructed encodings, i.e. those that consist of several values,
|
1529
|
+
* opposed to "primitive" encodings with just one single value.
|
1530
|
+
* Primitive values that are encoded with "infinite length" are typically
|
1531
|
+
* constructed (their values come in multiple chunks) and are therefore
|
1532
|
+
* represented by instances of Constructive. The value of an Constructive
|
1533
|
+
* is always an Array.
|
1534
|
+
*
|
1535
|
+
* ==== ASN1::Set and ASN1::Sequence
|
1536
|
+
*
|
1537
|
+
* The most common constructive encodings are SETs and SEQUENCEs, which is
|
1538
|
+
* why there are two sub-classes of Constructive representing each of
|
1539
|
+
* them.
|
1540
|
+
*
|
1541
|
+
* === Primitive
|
1542
|
+
*
|
1543
|
+
* This is the super class of all primitive values. Primitive
|
1544
|
+
* itself is not used when parsing ASN.1 data, all values are either
|
1545
|
+
* instances of a corresponding sub-class of Primitive or they are
|
1546
|
+
* instances of ASN1Data if the value was tagged implicitly or explicitly.
|
1547
|
+
* Please cf. Primitive documentation for details on sub-classes and
|
1548
|
+
* their respective mappings of ASN.1 data types to Ruby objects.
|
1549
|
+
*
|
1550
|
+
* == Possible values for +tagging+
|
1551
|
+
*
|
1552
|
+
* When constructing an ASN1Data object the ASN.1 type definition may
|
1553
|
+
* require certain elements to be either implicitly or explicitly tagged.
|
1554
|
+
* This can be achieved by setting the +tagging+ attribute manually for
|
1555
|
+
* sub-classes of ASN1Data. Use the symbol +:IMPLICIT+ for implicit
|
1556
|
+
* tagging and +:EXPLICIT+ if the element requires explicit tagging.
|
1557
|
+
*
|
1558
|
+
* == Possible values for +tag_class+
|
1559
|
+
*
|
1560
|
+
* It is possible to create arbitrary ASN1Data objects that also support
|
1561
|
+
* a PRIVATE or APPLICATION tag class. Possible values for the +tag_class+
|
1562
|
+
* attribute are:
|
1563
|
+
* * +:UNIVERSAL+ (the default for untagged values)
|
1564
|
+
* * +:CONTEXT_SPECIFIC+ (the default for tagged values)
|
1565
|
+
* * +:APPLICATION+
|
1566
|
+
* * +:PRIVATE+
|
1567
|
+
*
|
1568
|
+
* == Tag constants
|
1569
|
+
*
|
1570
|
+
* There is a constant defined for each universal tag:
|
1571
|
+
* * OpenSSL::ASN1::EOC (0)
|
1572
|
+
* * OpenSSL::ASN1::BOOLEAN (1)
|
1573
|
+
* * OpenSSL::ASN1::INTEGER (2)
|
1574
|
+
* * OpenSSL::ASN1::BIT_STRING (3)
|
1575
|
+
* * OpenSSL::ASN1::OCTET_STRING (4)
|
1576
|
+
* * OpenSSL::ASN1::NULL (5)
|
1577
|
+
* * OpenSSL::ASN1::OBJECT (6)
|
1578
|
+
* * OpenSSL::ASN1::ENUMERATED (10)
|
1579
|
+
* * OpenSSL::ASN1::UTF8STRING (12)
|
1580
|
+
* * OpenSSL::ASN1::SEQUENCE (16)
|
1581
|
+
* * OpenSSL::ASN1::SET (17)
|
1582
|
+
* * OpenSSL::ASN1::NUMERICSTRING (18)
|
1583
|
+
* * OpenSSL::ASN1::PRINTABLESTRING (19)
|
1584
|
+
* * OpenSSL::ASN1::T61STRING (20)
|
1585
|
+
* * OpenSSL::ASN1::VIDEOTEXSTRING (21)
|
1586
|
+
* * OpenSSL::ASN1::IA5STRING (22)
|
1587
|
+
* * OpenSSL::ASN1::UTCTIME (23)
|
1588
|
+
* * OpenSSL::ASN1::GENERALIZEDTIME (24)
|
1589
|
+
* * OpenSSL::ASN1::GRAPHICSTRING (25)
|
1590
|
+
* * OpenSSL::ASN1::ISO64STRING (26)
|
1591
|
+
* * OpenSSL::ASN1::GENERALSTRING (27)
|
1592
|
+
* * OpenSSL::ASN1::UNIVERSALSTRING (28)
|
1593
|
+
* * OpenSSL::ASN1::BMPSTRING (30)
|
1594
|
+
*
|
1595
|
+
* == UNIVERSAL_TAG_NAME constant
|
1596
|
+
*
|
1597
|
+
* An Array that stores the name of a given tag number. These names are
|
1598
|
+
* the same as the name of the tag constant that is additionally defined,
|
1599
|
+
* e.g. UNIVERSAL_TAG_NAME[2] = "INTEGER" and OpenSSL::ASN1::INTEGER = 2.
|
1600
|
+
*
|
1601
|
+
* == Example usage
|
1602
|
+
*
|
1603
|
+
* === Decoding and viewing a DER-encoded file
|
1604
|
+
* require 'openssl'
|
1605
|
+
* require 'pp'
|
1606
|
+
* der = File.binread('data.der')
|
1607
|
+
* asn1 = OpenSSL::ASN1.decode(der)
|
1608
|
+
* pp der
|
1609
|
+
*
|
1610
|
+
* === Creating an ASN.1 structure and DER-encoding it
|
1611
|
+
* require 'openssl'
|
1612
|
+
* version = OpenSSL::ASN1::Integer.new(1)
|
1613
|
+
* # Explicitly 0-tagged implies context-specific tag class
|
1614
|
+
* serial = OpenSSL::ASN1::Integer.new(12345, 0, :EXPLICIT, :CONTEXT_SPECIFIC)
|
1615
|
+
* name = OpenSSL::ASN1::PrintableString.new('Data 1')
|
1616
|
+
* sequence = OpenSSL::ASN1::Sequence.new( [ version, serial, name ] )
|
1617
|
+
* der = sequence.to_der
|
1618
|
+
*/
|
1619
|
+
mASN1 = rb_define_module_under(mOSSL, "ASN1");
|
1620
|
+
|
1621
|
+
/* Document-class: OpenSSL::ASN1::ASN1Error
|
1622
|
+
*
|
1623
|
+
* Generic error class for all errors raised in ASN1 and any of the
|
1624
|
+
* classes defined in it.
|
1625
|
+
*/
|
1626
|
+
eASN1Error = rb_define_class_under(mASN1, "ASN1Error", eOSSLError);
|
1627
|
+
rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1);
|
1628
|
+
rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1);
|
1629
|
+
rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1);
|
1630
|
+
ary = rb_ary_new();
|
1631
|
+
|
1632
|
+
/*
|
1633
|
+
* Array storing tag names at the tag's index.
|
1634
|
+
*/
|
1635
|
+
rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
|
1636
|
+
for(i = 0; i < ossl_asn1_info_size; i++){
|
1637
|
+
if(ossl_asn1_info[i].name[0] == '[') continue;
|
1638
|
+
rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i));
|
1639
|
+
rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name));
|
1640
|
+
}
|
1641
|
+
|
1642
|
+
/* Document-class: OpenSSL::ASN1::ASN1Data
|
1643
|
+
*
|
1644
|
+
* The top-level class representing any ASN.1 object. When parsed by
|
1645
|
+
* ASN1.decode, tagged values are always represented by an instance
|
1646
|
+
* of ASN1Data.
|
1647
|
+
*
|
1648
|
+
* == The role of ASN1Data for parsing tagged values
|
1649
|
+
*
|
1650
|
+
* When encoding an ASN.1 type it is inherently clear what original
|
1651
|
+
* type (e.g. INTEGER, OCTET STRING etc.) this value has, regardless
|
1652
|
+
* of its tagging.
|
1653
|
+
* But opposed to the time an ASN.1 type is to be encoded, when parsing
|
1654
|
+
* them it is not possible to deduce the "real type" of tagged
|
1655
|
+
* values. This is why tagged values are generally parsed into ASN1Data
|
1656
|
+
* instances, but with a different outcome for implicit and explicit
|
1657
|
+
* tagging.
|
1658
|
+
*
|
1659
|
+
* === Example of a parsed implicitly tagged value
|
1660
|
+
*
|
1661
|
+
* An implicitly 1-tagged INTEGER value will be parsed as an
|
1662
|
+
* ASN1Data with
|
1663
|
+
* * +tag+ equal to 1
|
1664
|
+
* * +tag_class+ equal to +:CONTEXT_SPECIFIC+
|
1665
|
+
* * +value+ equal to a +String+ that carries the raw encoding
|
1666
|
+
* of the INTEGER.
|
1667
|
+
* This implies that a subsequent decoding step is required to
|
1668
|
+
* completely decode implicitly tagged values.
|
1669
|
+
*
|
1670
|
+
* === Example of a parsed explicitly tagged value
|
1671
|
+
*
|
1672
|
+
* An explicitly 1-tagged INTEGER value will be parsed as an
|
1673
|
+
* ASN1Data with
|
1674
|
+
* * +tag+ equal to 1
|
1675
|
+
* * +tag_class+ equal to +:CONTEXT_SPECIFIC+
|
1676
|
+
* * +value+ equal to an +Array+ with one single element, an
|
1677
|
+
* instance of OpenSSL::ASN1::Integer, i.e. the inner element
|
1678
|
+
* is the non-tagged primitive value, and the tagging is represented
|
1679
|
+
* in the outer ASN1Data
|
1680
|
+
*
|
1681
|
+
* == Example - Decoding an implicitly tagged INTEGER
|
1682
|
+
* int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT) # implicit 0-tagged
|
1683
|
+
* seq = OpenSSL::ASN1::Sequence.new( [int] )
|
1684
|
+
* der = seq.to_der
|
1685
|
+
* asn1 = OpenSSL::ASN1.decode(der)
|
1686
|
+
* # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
|
1687
|
+
* # @infinite_length=false,
|
1688
|
+
* # @tag=16,
|
1689
|
+
* # @tag_class=:UNIVERSAL,
|
1690
|
+
* # @tagging=nil,
|
1691
|
+
* # @value=
|
1692
|
+
* # [#<OpenSSL::ASN1::ASN1Data:0x87326f4
|
1693
|
+
* # @infinite_length=false,
|
1694
|
+
* # @tag=0,
|
1695
|
+
* # @tag_class=:CONTEXT_SPECIFIC,
|
1696
|
+
* # @value="\x01">]>
|
1697
|
+
* raw_int = asn1.value[0]
|
1698
|
+
* # manually rewrite tag and tag class to make it an UNIVERSAL value
|
1699
|
+
* raw_int.tag = OpenSSL::ASN1::INTEGER
|
1700
|
+
* raw_int.tag_class = :UNIVERSAL
|
1701
|
+
* int2 = OpenSSL::ASN1.decode(raw_int)
|
1702
|
+
* puts int2.value # => 1
|
1703
|
+
*
|
1704
|
+
* == Example - Decoding an explicitly tagged INTEGER
|
1705
|
+
* int = OpenSSL::ASN1::Integer.new(1, 0, :EXPLICIT) # explicit 0-tagged
|
1706
|
+
* seq = OpenSSL::ASN1::Sequence.new( [int] )
|
1707
|
+
* der = seq.to_der
|
1708
|
+
* asn1 = OpenSSL::ASN1.decode(der)
|
1709
|
+
* # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
|
1710
|
+
* # @infinite_length=false,
|
1711
|
+
* # @tag=16,
|
1712
|
+
* # @tag_class=:UNIVERSAL,
|
1713
|
+
* # @tagging=nil,
|
1714
|
+
* # @value=
|
1715
|
+
* # [#<OpenSSL::ASN1::ASN1Data:0x87326f4
|
1716
|
+
* # @infinite_length=false,
|
1717
|
+
* # @tag=0,
|
1718
|
+
* # @tag_class=:CONTEXT_SPECIFIC,
|
1719
|
+
* # @value=
|
1720
|
+
* # [#<OpenSSL::ASN1::Integer:0x85bf308
|
1721
|
+
* # @infinite_length=false,
|
1722
|
+
* # @tag=2,
|
1723
|
+
* # @tag_class=:UNIVERSAL
|
1724
|
+
* # @tagging=nil,
|
1725
|
+
* # @value=1>]>]>
|
1726
|
+
* int2 = asn1.value[0].value[0]
|
1727
|
+
* puts int2.value # => 1
|
1728
|
+
*/
|
1729
|
+
cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
|
1730
|
+
/*
|
1731
|
+
* Carries the value of a ASN.1 type.
|
1732
|
+
* Please confer Constructive and Primitive for the mappings between
|
1733
|
+
* ASN.1 data types and Ruby classes.
|
1734
|
+
*/
|
1735
|
+
rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
|
1736
|
+
/*
|
1737
|
+
* A +Number+ representing the tag number of this ASN1Data. Never +nil+.
|
1738
|
+
*/
|
1739
|
+
rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
|
1740
|
+
/*
|
1741
|
+
* A +Symbol+ representing the tag class of this ASN1Data. Never +nil+.
|
1742
|
+
* See ASN1Data for possible values.
|
1743
|
+
*/
|
1744
|
+
rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
|
1745
|
+
/*
|
1746
|
+
* Never +nil+. A +Boolean+ indicating whether the encoding was infinite
|
1747
|
+
* length (in the case of parsing) or whether an infinite length encoding
|
1748
|
+
* shall be used (in the encoding case).
|
1749
|
+
* In DER, every value has a finite length associated with it. But in
|
1750
|
+
* scenarios where large amounts of data need to be transferred it
|
1751
|
+
* might be desirable to have some kind of streaming support available.
|
1752
|
+
* For example, huge OCTET STRINGs are preferably sent in smaller-sized
|
1753
|
+
* chunks, each at a time.
|
1754
|
+
* This is possible in BER by setting the length bytes of an encoding
|
1755
|
+
* to zero and by this indicating that the following value will be
|
1756
|
+
* sent in chunks. Infinite length encodings are always constructed.
|
1757
|
+
* The end of such a stream of chunks is indicated by sending a EOC
|
1758
|
+
* (End of Content) tag. SETs and SEQUENCEs may use an infinite length
|
1759
|
+
* encoding, but also primitive types such as e.g. OCTET STRINGS or
|
1760
|
+
* BIT STRINGS may leverage this functionality (cf. ITU-T X.690).
|
1761
|
+
*/
|
1762
|
+
rb_attr(cASN1Data, rb_intern("infinite_length"), 1, 1, 0);
|
1763
|
+
rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
|
1764
|
+
rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
|
1765
|
+
|
1766
|
+
/* Document-class: OpenSSL::ASN1::Primitive
|
1767
|
+
*
|
1768
|
+
* The parent class for all primitive encodings. Attributes are the same as
|
1769
|
+
* for ASN1Data, with the addition of +tagging+.
|
1770
|
+
* Primitive values can never be infinite length encodings, thus it is not
|
1771
|
+
* possible to set the +infinite_length+ attribute for Primitive and its
|
1772
|
+
* sub-classes.
|
1773
|
+
*
|
1774
|
+
* == Primitive sub-classes and their mapping to Ruby classes
|
1775
|
+
* * OpenSSL::ASN1::EndOfContent <=> +value+ is always +nil+
|
1776
|
+
* * OpenSSL::ASN1::Boolean <=> +value+ is a +Boolean+
|
1777
|
+
* * OpenSSL::ASN1::Integer <=> +value+ is a +Number+
|
1778
|
+
* * OpenSSL::ASN1::BitString <=> +value+ is a +String+
|
1779
|
+
* * OpenSSL::ASN1::OctetString <=> +value+ is a +String+
|
1780
|
+
* * OpenSSL::ASN1::Null <=> +value+ is always +nil+
|
1781
|
+
* * OpenSSL::ASN1::Object <=> +value+ is a +String+
|
1782
|
+
* * OpenSSL::ASN1::Enumerated <=> +value+ is a +Number+
|
1783
|
+
* * OpenSSL::ASN1::UTF8String <=> +value+ is a +String+
|
1784
|
+
* * OpenSSL::ASN1::NumericString <=> +value+ is a +String+
|
1785
|
+
* * OpenSSL::ASN1::PrintableString <=> +value+ is a +String+
|
1786
|
+
* * OpenSSL::ASN1::T61String <=> +value+ is a +String+
|
1787
|
+
* * OpenSSL::ASN1::VideotexString <=> +value+ is a +String+
|
1788
|
+
* * OpenSSL::ASN1::IA5String <=> +value+ is a +String+
|
1789
|
+
* * OpenSSL::ASN1::UTCTime <=> +value+ is a +Time+
|
1790
|
+
* * OpenSSL::ASN1::GeneralizedTime <=> +value+ is a +Time+
|
1791
|
+
* * OpenSSL::ASN1::GraphicString <=> +value+ is a +String+
|
1792
|
+
* * OpenSSL::ASN1::ISO64String <=> +value+ is a +String+
|
1793
|
+
* * OpenSSL::ASN1::GeneralString <=> +value+ is a +String+
|
1794
|
+
* * OpenSSL::ASN1::UniversalString <=> +value+ is a +String+
|
1795
|
+
* * OpenSSL::ASN1::BMPString <=> +value+ is a +String+
|
1796
|
+
*
|
1797
|
+
* == OpenSSL::ASN1::BitString
|
1798
|
+
*
|
1799
|
+
* === Additional attributes
|
1800
|
+
* +unused_bits+: if the underlying BIT STRING's
|
1801
|
+
* length is a multiple of 8 then +unused_bits+ is 0. Otherwise
|
1802
|
+
* +unused_bits+ indicates the number of bits that are to be ignored in
|
1803
|
+
* the final octet of the +BitString+'s +value+.
|
1804
|
+
*
|
1805
|
+
* == OpenSSL::ASN1::ObjectId
|
1806
|
+
*
|
1807
|
+
* NOTE: While OpenSSL::ASN1::ObjectId.new will allocate a new ObjectId,
|
1808
|
+
* it is not typically allocated this way, but rather that are received from
|
1809
|
+
* parsed ASN1 encodings.
|
1810
|
+
*
|
1811
|
+
* === Additional attributes
|
1812
|
+
* * +sn+: the short name as defined in <openssl/objects.h>.
|
1813
|
+
* * +ln+: the long name as defined in <openssl/objects.h>.
|
1814
|
+
* * +oid+: the object identifier as a +String+, e.g. "1.2.3.4.5"
|
1815
|
+
* * +short_name+: alias for +sn+.
|
1816
|
+
* * +long_name+: alias for +ln+.
|
1817
|
+
*
|
1818
|
+
* == Examples
|
1819
|
+
* With the Exception of OpenSSL::ASN1::EndOfContent, each Primitive class
|
1820
|
+
* constructor takes at least one parameter, the +value+.
|
1821
|
+
*
|
1822
|
+
* === Creating EndOfContent
|
1823
|
+
* eoc = OpenSSL::ASN1::EndOfContent.new
|
1824
|
+
*
|
1825
|
+
* === Creating any other Primitive
|
1826
|
+
* prim = <class>.new(value) # <class> being one of the sub-classes except EndOfContent
|
1827
|
+
* prim_zero_tagged_implicit = <class>.new(value, 0, :IMPLICIT)
|
1828
|
+
* prim_zero_tagged_explicit = <class>.new(value, 0, :EXPLICIT)
|
1829
|
+
*/
|
1830
|
+
cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data);
|
1831
|
+
/*
|
1832
|
+
* May be used as a hint for encoding a value either implicitly or
|
1833
|
+
* explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
|
1834
|
+
* +tagging+ is not set when a ASN.1 structure is parsed using
|
1835
|
+
* OpenSSL::ASN1.decode.
|
1836
|
+
*/
|
1837
|
+
rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
|
1838
|
+
rb_undef_method(cASN1Primitive, "infinite_length=");
|
1839
|
+
rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
|
1840
|
+
rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);
|
1841
|
+
|
1842
|
+
/* Document-class: OpenSSL::ASN1::Constructive
|
1843
|
+
*
|
1844
|
+
* The parent class for all constructed encodings. The +value+ attribute
|
1845
|
+
* of a Constructive is always an +Array+. Attributes are the same as
|
1846
|
+
* for ASN1Data, with the addition of +tagging+.
|
1847
|
+
*
|
1848
|
+
* == SET and SEQUENCE
|
1849
|
+
*
|
1850
|
+
* Most constructed encodings come in the form of a SET or a SEQUENCE.
|
1851
|
+
* These encodings are represented by one of the two sub-classes of
|
1852
|
+
* Constructive:
|
1853
|
+
* * OpenSSL::ASN1::Set
|
1854
|
+
* * OpenSSL::ASN1::Sequence
|
1855
|
+
* Please note that tagged sequences and sets are still parsed as
|
1856
|
+
* instances of ASN1Data. Find further details on tagged values
|
1857
|
+
* there.
|
1858
|
+
*
|
1859
|
+
* === Example - constructing a SEQUENCE
|
1860
|
+
* int = OpenSSL::ASN1::Integer.new(1)
|
1861
|
+
* str = OpenSSL::ASN1::PrintableString.new('abc')
|
1862
|
+
* sequence = OpenSSL::ASN1::Sequence.new( [ int, str ] )
|
1863
|
+
*
|
1864
|
+
* === Example - constructing a SET
|
1865
|
+
* int = OpenSSL::ASN1::Integer.new(1)
|
1866
|
+
* str = OpenSSL::ASN1::PrintableString.new('abc')
|
1867
|
+
* set = OpenSSL::ASN1::Set.new( [ int, str ] )
|
1868
|
+
*
|
1869
|
+
* == Infinite length primitive values
|
1870
|
+
*
|
1871
|
+
* The only case where Constructive is used directly is for infinite
|
1872
|
+
* length encodings of primitive values. These encodings are always
|
1873
|
+
* constructed, with the contents of the +value+ +Array+ being either
|
1874
|
+
* UNIVERSAL non-infinite length partial encodings of the actual value
|
1875
|
+
* or again constructive encodings with infinite length (i.e. infinite
|
1876
|
+
* length primitive encodings may be constructed recursively with another
|
1877
|
+
* infinite length value within an already infinite length value). Each
|
1878
|
+
* partial encoding must be of the same UNIVERSAL type as the overall
|
1879
|
+
* encoding. The value of the overall encoding consists of the
|
1880
|
+
* concatenation of each partial encoding taken in sequence. The +value+
|
1881
|
+
* array of the outer infinite length value must end with a
|
1882
|
+
* OpenSSL::ASN1::EndOfContent instance.
|
1883
|
+
*
|
1884
|
+
* Please note that it is not possible to encode Constructive without
|
1885
|
+
* the +infinite_length+ attribute being set to +true+, use
|
1886
|
+
* OpenSSL::ASN1::Sequence or OpenSSL::ASN1::Set in these cases instead.
|
1887
|
+
*
|
1888
|
+
* === Example - Infinite length OCTET STRING
|
1889
|
+
* partial1 = OpenSSL::ASN1::OctetString.new("\x01")
|
1890
|
+
* partial2 = OpenSSL::ASN1::OctetString.new("\x02")
|
1891
|
+
* inf_octets = OpenSSL::ASN1::Constructive.new( [ partial1,
|
1892
|
+
* partial2,
|
1893
|
+
* OpenSSL::ASN1::EndOfContent.new ],
|
1894
|
+
* OpenSSL::ASN1::OCTET_STRING,
|
1895
|
+
* nil,
|
1896
|
+
* :UNIVERSAL )
|
1897
|
+
* # The real value of inf_octets is "\x01\x02", i.e. the concatenation
|
1898
|
+
* # of partial1 and partial2
|
1899
|
+
* inf_octets.infinite_length = true
|
1900
|
+
* der = inf_octets.to_der
|
1901
|
+
* asn1 = OpenSSL::ASN1.decode(der)
|
1902
|
+
* puts asn1.infinite_length # => true
|
1903
|
+
*/
|
1904
|
+
cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data);
|
1905
|
+
rb_include_module(cASN1Constructive, rb_mEnumerable);
|
1906
|
+
/*
|
1907
|
+
* May be used as a hint for encoding a value either implicitly or
|
1908
|
+
* explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
|
1909
|
+
* +tagging+ is not set when a ASN.1 structure is parsed using
|
1910
|
+
* OpenSSL::ASN1.decode.
|
1911
|
+
*/
|
1912
|
+
rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
|
1913
|
+
rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
|
1914
|
+
rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0);
|
1915
|
+
rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0);
|
1916
|
+
|
1917
|
+
#define OSSL_ASN1_DEFINE_CLASS(name, super) \
|
1918
|
+
do{\
|
1919
|
+
cASN1##name = rb_define_class_under(mASN1, #name, cASN1##super);\
|
1920
|
+
rb_define_module_function(mASN1, #name, ossl_asn1_##name, -1);\
|
1921
|
+
}while(0)
|
1922
|
+
|
1923
|
+
OSSL_ASN1_DEFINE_CLASS(Boolean, Primitive);
|
1924
|
+
OSSL_ASN1_DEFINE_CLASS(Integer, Primitive);
|
1925
|
+
OSSL_ASN1_DEFINE_CLASS(Enumerated, Primitive);
|
1926
|
+
OSSL_ASN1_DEFINE_CLASS(BitString, Primitive);
|
1927
|
+
OSSL_ASN1_DEFINE_CLASS(OctetString, Primitive);
|
1928
|
+
OSSL_ASN1_DEFINE_CLASS(UTF8String, Primitive);
|
1929
|
+
OSSL_ASN1_DEFINE_CLASS(NumericString, Primitive);
|
1930
|
+
OSSL_ASN1_DEFINE_CLASS(PrintableString, Primitive);
|
1931
|
+
OSSL_ASN1_DEFINE_CLASS(T61String, Primitive);
|
1932
|
+
OSSL_ASN1_DEFINE_CLASS(VideotexString, Primitive);
|
1933
|
+
OSSL_ASN1_DEFINE_CLASS(IA5String, Primitive);
|
1934
|
+
OSSL_ASN1_DEFINE_CLASS(GraphicString, Primitive);
|
1935
|
+
OSSL_ASN1_DEFINE_CLASS(ISO64String, Primitive);
|
1936
|
+
OSSL_ASN1_DEFINE_CLASS(GeneralString, Primitive);
|
1937
|
+
OSSL_ASN1_DEFINE_CLASS(UniversalString, Primitive);
|
1938
|
+
OSSL_ASN1_DEFINE_CLASS(BMPString, Primitive);
|
1939
|
+
OSSL_ASN1_DEFINE_CLASS(Null, Primitive);
|
1940
|
+
OSSL_ASN1_DEFINE_CLASS(ObjectId, Primitive);
|
1941
|
+
OSSL_ASN1_DEFINE_CLASS(UTCTime, Primitive);
|
1942
|
+
OSSL_ASN1_DEFINE_CLASS(GeneralizedTime, Primitive);
|
1943
|
+
|
1944
|
+
OSSL_ASN1_DEFINE_CLASS(Sequence, Constructive);
|
1945
|
+
OSSL_ASN1_DEFINE_CLASS(Set, Constructive);
|
1946
|
+
|
1947
|
+
OSSL_ASN1_DEFINE_CLASS(EndOfContent, Data);
|
1948
|
+
|
1949
|
+
|
1950
|
+
/* Document-class: OpenSSL::ASN1::ObjectId
|
1951
|
+
*
|
1952
|
+
* Represents the primitive object id for OpenSSL::ASN1
|
1953
|
+
*/
|
1954
|
+
#if 0
|
1955
|
+
cASN1ObjectId = rb_define_class_under(mASN1, "ObjectId", cASN1Primitive); /* let rdoc know */
|
1956
|
+
#endif
|
1957
|
+
rb_define_singleton_method(cASN1ObjectId, "register", ossl_asn1obj_s_register, 3);
|
1958
|
+
rb_define_method(cASN1ObjectId, "sn", ossl_asn1obj_get_sn, 0);
|
1959
|
+
rb_define_method(cASN1ObjectId, "ln", ossl_asn1obj_get_ln, 0);
|
1960
|
+
rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
|
1961
|
+
rb_define_alias(cASN1ObjectId, "short_name", "sn");
|
1962
|
+
rb_define_alias(cASN1ObjectId, "long_name", "ln");
|
1963
|
+
rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
|
1964
|
+
|
1965
|
+
rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
|
1966
|
+
|
1967
|
+
class_tag_map = rb_hash_new();
|
1968
|
+
rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC));
|
1969
|
+
rb_hash_aset(class_tag_map, cASN1Boolean, INT2NUM(V_ASN1_BOOLEAN));
|
1970
|
+
rb_hash_aset(class_tag_map, cASN1Integer, INT2NUM(V_ASN1_INTEGER));
|
1971
|
+
rb_hash_aset(class_tag_map, cASN1BitString, INT2NUM(V_ASN1_BIT_STRING));
|
1972
|
+
rb_hash_aset(class_tag_map, cASN1OctetString, INT2NUM(V_ASN1_OCTET_STRING));
|
1973
|
+
rb_hash_aset(class_tag_map, cASN1Null, INT2NUM(V_ASN1_NULL));
|
1974
|
+
rb_hash_aset(class_tag_map, cASN1ObjectId, INT2NUM(V_ASN1_OBJECT));
|
1975
|
+
rb_hash_aset(class_tag_map, cASN1Enumerated, INT2NUM(V_ASN1_ENUMERATED));
|
1976
|
+
rb_hash_aset(class_tag_map, cASN1UTF8String, INT2NUM(V_ASN1_UTF8STRING));
|
1977
|
+
rb_hash_aset(class_tag_map, cASN1Sequence, INT2NUM(V_ASN1_SEQUENCE));
|
1978
|
+
rb_hash_aset(class_tag_map, cASN1Set, INT2NUM(V_ASN1_SET));
|
1979
|
+
rb_hash_aset(class_tag_map, cASN1NumericString, INT2NUM(V_ASN1_NUMERICSTRING));
|
1980
|
+
rb_hash_aset(class_tag_map, cASN1PrintableString, INT2NUM(V_ASN1_PRINTABLESTRING));
|
1981
|
+
rb_hash_aset(class_tag_map, cASN1T61String, INT2NUM(V_ASN1_T61STRING));
|
1982
|
+
rb_hash_aset(class_tag_map, cASN1VideotexString, INT2NUM(V_ASN1_VIDEOTEXSTRING));
|
1983
|
+
rb_hash_aset(class_tag_map, cASN1IA5String, INT2NUM(V_ASN1_IA5STRING));
|
1984
|
+
rb_hash_aset(class_tag_map, cASN1UTCTime, INT2NUM(V_ASN1_UTCTIME));
|
1985
|
+
rb_hash_aset(class_tag_map, cASN1GeneralizedTime, INT2NUM(V_ASN1_GENERALIZEDTIME));
|
1986
|
+
rb_hash_aset(class_tag_map, cASN1GraphicString, INT2NUM(V_ASN1_GRAPHICSTRING));
|
1987
|
+
rb_hash_aset(class_tag_map, cASN1ISO64String, INT2NUM(V_ASN1_ISO64STRING));
|
1988
|
+
rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
|
1989
|
+
rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
|
1990
|
+
rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
|
1991
|
+
rb_global_variable(&class_tag_map);
|
1992
|
+
}
|