openssl 2.1.1 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +9 -7
- data/History.md +165 -0
- data/README.md +2 -2
- data/ext/openssl/extconf.rb +51 -27
- data/ext/openssl/openssl_missing.h +39 -4
- data/ext/openssl/ossl.c +61 -27
- data/ext/openssl/ossl.h +8 -5
- data/ext/openssl/ossl_asn1.c +27 -1
- data/ext/openssl/ossl_bn.c +92 -24
- data/ext/openssl/ossl_bn.h +2 -1
- data/ext/openssl/ossl_cipher.c +33 -24
- data/ext/openssl/ossl_digest.c +22 -53
- data/ext/openssl/ossl_engine.c +2 -12
- data/ext/openssl/ossl_hmac.c +5 -11
- data/ext/openssl/ossl_kdf.c +3 -19
- data/ext/openssl/ossl_ns_spki.c +1 -1
- data/ext/openssl/ossl_ocsp.c +6 -11
- data/ext/openssl/ossl_ocsp.h +3 -3
- data/ext/openssl/ossl_pkcs12.c +1 -0
- data/ext/openssl/ossl_pkcs7.c +4 -19
- data/ext/openssl/ossl_pkcs7.h +16 -0
- data/ext/openssl/ossl_pkey.c +206 -17
- data/ext/openssl/ossl_pkey.h +6 -6
- data/ext/openssl/ossl_pkey_dh.c +1 -1
- data/ext/openssl/ossl_pkey_dsa.c +2 -2
- data/ext/openssl/ossl_pkey_ec.c +38 -8
- data/ext/openssl/ossl_pkey_rsa.c +17 -9
- data/ext/openssl/ossl_rand.c +2 -40
- data/ext/openssl/ossl_ssl.c +205 -75
- data/ext/openssl/ossl_ts.c +1524 -0
- data/ext/openssl/ossl_ts.h +16 -0
- data/ext/openssl/ossl_x509.c +91 -0
- data/ext/openssl/ossl_x509cert.c +2 -2
- data/ext/openssl/ossl_x509ext.c +15 -0
- data/ext/openssl/ossl_x509name.c +15 -10
- data/ext/openssl/ossl_x509store.c +40 -22
- data/lib/openssl/bn.rb +1 -1
- data/lib/openssl/buffering.rb +33 -17
- data/lib/openssl/cipher.rb +1 -1
- data/lib/openssl/config.rb +53 -26
- data/lib/openssl/digest.rb +10 -12
- data/lib/openssl/hmac.rb +13 -0
- data/lib/openssl/marshal.rb +30 -0
- data/lib/openssl/pkcs5.rb +1 -1
- data/lib/openssl/pkey.rb +18 -1
- data/lib/openssl/ssl.rb +46 -7
- data/lib/openssl/version.rb +5 -0
- data/lib/openssl/x509.rb +155 -1
- data/lib/openssl.rb +25 -9
- metadata +25 -9
- data/ext/openssl/deprecation.rb +0 -23
- data/ext/openssl/ossl_version.h +0 -15
@@ -0,0 +1,1524 @@
|
|
1
|
+
/*
|
2
|
+
*
|
3
|
+
* Copyright (C) 2010 Martin Bosslet <Martin.Bosslet@googlemail.com>
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licenced under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#include "ossl.h"
|
11
|
+
|
12
|
+
#ifndef OPENSSL_NO_TS
|
13
|
+
|
14
|
+
#define NewTSRequest(klass) \
|
15
|
+
TypedData_Wrap_Struct((klass), &ossl_ts_req_type, 0)
|
16
|
+
#define SetTSRequest(obj, req) do { \
|
17
|
+
if (!(req)) { \
|
18
|
+
ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \
|
19
|
+
} \
|
20
|
+
RTYPEDDATA_DATA(obj) = (req); \
|
21
|
+
} while (0)
|
22
|
+
#define GetTSRequest(obj, req) do { \
|
23
|
+
TypedData_Get_Struct((obj), TS_REQ, &ossl_ts_req_type, (req)); \
|
24
|
+
if (!(req)) { \
|
25
|
+
ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \
|
26
|
+
} \
|
27
|
+
} while (0)
|
28
|
+
|
29
|
+
#define NewTSResponse(klass) \
|
30
|
+
TypedData_Wrap_Struct((klass), &ossl_ts_resp_type, 0)
|
31
|
+
#define SetTSResponse(obj, resp) do { \
|
32
|
+
if (!(resp)) { \
|
33
|
+
ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \
|
34
|
+
} \
|
35
|
+
RTYPEDDATA_DATA(obj) = (resp); \
|
36
|
+
} while (0)
|
37
|
+
#define GetTSResponse(obj, resp) do { \
|
38
|
+
TypedData_Get_Struct((obj), TS_RESP, &ossl_ts_resp_type, (resp)); \
|
39
|
+
if (!(resp)) { \
|
40
|
+
ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \
|
41
|
+
} \
|
42
|
+
} while (0)
|
43
|
+
|
44
|
+
#define NewTSTokenInfo(klass) \
|
45
|
+
TypedData_Wrap_Struct((klass), &ossl_ts_token_info_type, 0)
|
46
|
+
#define SetTSTokenInfo(obj, info) do { \
|
47
|
+
if (!(info)) { \
|
48
|
+
ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \
|
49
|
+
} \
|
50
|
+
RTYPEDDATA_DATA(obj) = (info); \
|
51
|
+
} while (0)
|
52
|
+
#define GetTSTokenInfo(obj, info) do { \
|
53
|
+
TypedData_Get_Struct((obj), TS_TST_INFO, &ossl_ts_token_info_type, (info)); \
|
54
|
+
if (!(info)) { \
|
55
|
+
ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \
|
56
|
+
} \
|
57
|
+
} while (0)
|
58
|
+
|
59
|
+
#define ossl_tsfac_get_default_policy_id(o) rb_attr_get((o),rb_intern("@default_policy_id"))
|
60
|
+
#define ossl_tsfac_get_serial_number(o) rb_attr_get((o),rb_intern("@serial_number"))
|
61
|
+
#define ossl_tsfac_get_gen_time(o) rb_attr_get((o),rb_intern("@gen_time"))
|
62
|
+
#define ossl_tsfac_get_additional_certs(o) rb_attr_get((o),rb_intern("@additional_certs"))
|
63
|
+
#define ossl_tsfac_get_allowed_digests(o) rb_attr_get((o),rb_intern("@allowed_digests"))
|
64
|
+
|
65
|
+
static VALUE mTimestamp;
|
66
|
+
static VALUE eTimestampError;
|
67
|
+
static VALUE cTimestampRequest;
|
68
|
+
static VALUE cTimestampResponse;
|
69
|
+
static VALUE cTimestampTokenInfo;
|
70
|
+
static VALUE cTimestampFactory;
|
71
|
+
static VALUE sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE;
|
72
|
+
static VALUE sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE;
|
73
|
+
static VALUE sSYSTEM_FAILURE;
|
74
|
+
|
75
|
+
static void
|
76
|
+
ossl_ts_req_free(void *ptr)
|
77
|
+
{
|
78
|
+
TS_REQ_free(ptr);
|
79
|
+
}
|
80
|
+
|
81
|
+
static const rb_data_type_t ossl_ts_req_type = {
|
82
|
+
"OpenSSL/Timestamp/Request",
|
83
|
+
{
|
84
|
+
0, ossl_ts_req_free,
|
85
|
+
},
|
86
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
87
|
+
};
|
88
|
+
|
89
|
+
static void
|
90
|
+
ossl_ts_resp_free(void *ptr)
|
91
|
+
{
|
92
|
+
TS_RESP_free(ptr);
|
93
|
+
}
|
94
|
+
|
95
|
+
static const rb_data_type_t ossl_ts_resp_type = {
|
96
|
+
"OpenSSL/Timestamp/Response",
|
97
|
+
{
|
98
|
+
0, ossl_ts_resp_free,
|
99
|
+
},
|
100
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
101
|
+
};
|
102
|
+
|
103
|
+
static void
|
104
|
+
ossl_ts_token_info_free(void *ptr)
|
105
|
+
{
|
106
|
+
TS_TST_INFO_free(ptr);
|
107
|
+
}
|
108
|
+
|
109
|
+
static const rb_data_type_t ossl_ts_token_info_type = {
|
110
|
+
"OpenSSL/Timestamp/TokenInfo",
|
111
|
+
{
|
112
|
+
0, ossl_ts_token_info_free,
|
113
|
+
},
|
114
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
115
|
+
};
|
116
|
+
|
117
|
+
static VALUE
|
118
|
+
asn1_to_der(void *template, int (*i2d)(void *template, unsigned char **pp))
|
119
|
+
{
|
120
|
+
VALUE str;
|
121
|
+
int len;
|
122
|
+
unsigned char *p;
|
123
|
+
|
124
|
+
if((len = i2d(template, NULL)) <= 0)
|
125
|
+
ossl_raise(eTimestampError, "Error when encoding to DER");
|
126
|
+
str = rb_str_new(0, len);
|
127
|
+
p = (unsigned char *)RSTRING_PTR(str);
|
128
|
+
if(i2d(template, &p) <= 0)
|
129
|
+
ossl_raise(eTimestampError, "Error when encoding to DER");
|
130
|
+
rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str));
|
131
|
+
|
132
|
+
return str;
|
133
|
+
}
|
134
|
+
|
135
|
+
static ASN1_OBJECT*
|
136
|
+
obj_to_asn1obj(VALUE obj)
|
137
|
+
{
|
138
|
+
ASN1_OBJECT *a1obj;
|
139
|
+
|
140
|
+
StringValue(obj);
|
141
|
+
a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
|
142
|
+
if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
|
143
|
+
if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
|
144
|
+
|
145
|
+
return a1obj;
|
146
|
+
}
|
147
|
+
|
148
|
+
static VALUE
|
149
|
+
get_asn1obj(ASN1_OBJECT *obj)
|
150
|
+
{
|
151
|
+
BIO *out;
|
152
|
+
VALUE ret;
|
153
|
+
int nid;
|
154
|
+
if ((nid = OBJ_obj2nid(obj)) != NID_undef)
|
155
|
+
ret = rb_str_new2(OBJ_nid2sn(nid));
|
156
|
+
else{
|
157
|
+
if (!(out = BIO_new(BIO_s_mem())))
|
158
|
+
ossl_raise(eX509AttrError, NULL);
|
159
|
+
i2a_ASN1_OBJECT(out, obj);
|
160
|
+
ret = ossl_membio2str(out);
|
161
|
+
}
|
162
|
+
|
163
|
+
return ret;
|
164
|
+
}
|
165
|
+
|
166
|
+
static VALUE
|
167
|
+
ossl_ts_req_alloc(VALUE klass)
|
168
|
+
{
|
169
|
+
TS_REQ *req;
|
170
|
+
VALUE obj;
|
171
|
+
|
172
|
+
obj = NewTSRequest(klass);
|
173
|
+
if (!(req = TS_REQ_new()))
|
174
|
+
ossl_raise(eTimestampError, NULL);
|
175
|
+
SetTSRequest(obj, req);
|
176
|
+
|
177
|
+
/* Defaults */
|
178
|
+
TS_REQ_set_version(req, 1);
|
179
|
+
TS_REQ_set_cert_req(req, 1);
|
180
|
+
|
181
|
+
return obj;
|
182
|
+
}
|
183
|
+
|
184
|
+
/*
|
185
|
+
* When creating a Request with the +File+ or +string+ parameter, the
|
186
|
+
* corresponding +File+ or +string+ must be DER-encoded.
|
187
|
+
*
|
188
|
+
* call-seq:
|
189
|
+
* OpenSSL::Timestamp::Request.new(file) -> request
|
190
|
+
* OpenSSL::Timestamp::Request.new(string) -> request
|
191
|
+
* OpenSSL::Timestamp::Request.new -> empty request
|
192
|
+
*/
|
193
|
+
static VALUE
|
194
|
+
ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
|
195
|
+
{
|
196
|
+
TS_REQ *ts_req = DATA_PTR(self);
|
197
|
+
BIO *in;
|
198
|
+
VALUE arg;
|
199
|
+
|
200
|
+
if(rb_scan_args(argc, argv, "01", &arg) == 0) {
|
201
|
+
return self;
|
202
|
+
}
|
203
|
+
|
204
|
+
arg = ossl_to_der_if_possible(arg);
|
205
|
+
in = ossl_obj2bio(&arg);
|
206
|
+
ts_req = d2i_TS_REQ_bio(in, &ts_req);
|
207
|
+
BIO_free(in);
|
208
|
+
if (!ts_req) {
|
209
|
+
DATA_PTR(self) = NULL;
|
210
|
+
ossl_raise(eTimestampError, "Error when decoding the timestamp request");
|
211
|
+
}
|
212
|
+
DATA_PTR(self) = ts_req;
|
213
|
+
|
214
|
+
return self;
|
215
|
+
}
|
216
|
+
|
217
|
+
/*
|
218
|
+
* Returns the 'short name' of the object identifier that represents the
|
219
|
+
* algorithm that was used to create the message imprint digest.
|
220
|
+
*
|
221
|
+
* call-seq:
|
222
|
+
* request.algorithm -> string
|
223
|
+
*/
|
224
|
+
static VALUE
|
225
|
+
ossl_ts_req_get_algorithm(VALUE self)
|
226
|
+
{
|
227
|
+
TS_REQ *req;
|
228
|
+
TS_MSG_IMPRINT *mi;
|
229
|
+
X509_ALGOR *algor;
|
230
|
+
|
231
|
+
GetTSRequest(self, req);
|
232
|
+
mi = TS_REQ_get_msg_imprint(req);
|
233
|
+
algor = TS_MSG_IMPRINT_get_algo(mi);
|
234
|
+
return get_asn1obj(algor->algorithm);
|
235
|
+
}
|
236
|
+
|
237
|
+
/*
|
238
|
+
* Allows to set the object identifier or the 'short name' of the
|
239
|
+
* algorithm that was used to create the message imprint digest.
|
240
|
+
*
|
241
|
+
* ===Example:
|
242
|
+
* request.algorithm = "SHA1"
|
243
|
+
*
|
244
|
+
* call-seq:
|
245
|
+
* request.algorithm = "string" -> string
|
246
|
+
*/
|
247
|
+
static VALUE
|
248
|
+
ossl_ts_req_set_algorithm(VALUE self, VALUE algo)
|
249
|
+
{
|
250
|
+
TS_REQ *req;
|
251
|
+
TS_MSG_IMPRINT *mi;
|
252
|
+
ASN1_OBJECT *obj;
|
253
|
+
X509_ALGOR *algor;
|
254
|
+
|
255
|
+
GetTSRequest(self, req);
|
256
|
+
obj = obj_to_asn1obj(algo);
|
257
|
+
mi = TS_REQ_get_msg_imprint(req);
|
258
|
+
algor = TS_MSG_IMPRINT_get_algo(mi);
|
259
|
+
if (!X509_ALGOR_set0(algor, obj, V_ASN1_NULL, NULL)) {
|
260
|
+
ASN1_OBJECT_free(obj);
|
261
|
+
ossl_raise(eTimestampError, "X509_ALGOR_set0");
|
262
|
+
}
|
263
|
+
|
264
|
+
return algo;
|
265
|
+
}
|
266
|
+
|
267
|
+
/*
|
268
|
+
* Returns the message imprint (digest) of the data to be timestamped.
|
269
|
+
*
|
270
|
+
* call-seq:
|
271
|
+
* request.message_imprint -> string or nil
|
272
|
+
*/
|
273
|
+
static VALUE
|
274
|
+
ossl_ts_req_get_msg_imprint(VALUE self)
|
275
|
+
{
|
276
|
+
TS_REQ *req;
|
277
|
+
TS_MSG_IMPRINT *mi;
|
278
|
+
ASN1_OCTET_STRING *hashed_msg;
|
279
|
+
VALUE ret;
|
280
|
+
|
281
|
+
GetTSRequest(self, req);
|
282
|
+
mi = TS_REQ_get_msg_imprint(req);
|
283
|
+
hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
|
284
|
+
|
285
|
+
ret = rb_str_new((const char *)hashed_msg->data, hashed_msg->length);
|
286
|
+
|
287
|
+
return ret;
|
288
|
+
}
|
289
|
+
|
290
|
+
/*
|
291
|
+
* Set the message imprint digest.
|
292
|
+
*
|
293
|
+
* call-seq:
|
294
|
+
* request.message_imprint = "string" -> string
|
295
|
+
*/
|
296
|
+
static VALUE
|
297
|
+
ossl_ts_req_set_msg_imprint(VALUE self, VALUE hash)
|
298
|
+
{
|
299
|
+
TS_REQ *req;
|
300
|
+
TS_MSG_IMPRINT *mi;
|
301
|
+
StringValue(hash);
|
302
|
+
|
303
|
+
GetTSRequest(self, req);
|
304
|
+
mi = TS_REQ_get_msg_imprint(req);
|
305
|
+
if (!TS_MSG_IMPRINT_set_msg(mi, (unsigned char *)RSTRING_PTR(hash), RSTRING_LENINT(hash)))
|
306
|
+
ossl_raise(eTimestampError, "TS_MSG_IMPRINT_set_msg");
|
307
|
+
|
308
|
+
return hash;
|
309
|
+
}
|
310
|
+
|
311
|
+
/*
|
312
|
+
* Returns the version of this request. +1+ is the default value.
|
313
|
+
*
|
314
|
+
* call-seq:
|
315
|
+
* request.version -> Integer
|
316
|
+
*/
|
317
|
+
static VALUE
|
318
|
+
ossl_ts_req_get_version(VALUE self)
|
319
|
+
{
|
320
|
+
TS_REQ *req;
|
321
|
+
|
322
|
+
GetTSRequest(self, req);
|
323
|
+
return LONG2NUM(TS_REQ_get_version(req));
|
324
|
+
}
|
325
|
+
|
326
|
+
/*
|
327
|
+
* Sets the version number for this Request. This should be +1+ for compliant
|
328
|
+
* servers.
|
329
|
+
*
|
330
|
+
* call-seq:
|
331
|
+
* request.version = number -> Integer
|
332
|
+
*/
|
333
|
+
static VALUE
|
334
|
+
ossl_ts_req_set_version(VALUE self, VALUE version)
|
335
|
+
{
|
336
|
+
TS_REQ *req;
|
337
|
+
long ver;
|
338
|
+
|
339
|
+
if ((ver = NUM2LONG(version)) < 0)
|
340
|
+
ossl_raise(eTimestampError, "version must be >= 0!");
|
341
|
+
GetTSRequest(self, req);
|
342
|
+
if (!TS_REQ_set_version(req, ver))
|
343
|
+
ossl_raise(eTimestampError, "TS_REQ_set_version");
|
344
|
+
|
345
|
+
return version;
|
346
|
+
}
|
347
|
+
|
348
|
+
/*
|
349
|
+
* Returns the 'short name' of the object identifier that represents the
|
350
|
+
* timestamp policy under which the server shall create the timestamp.
|
351
|
+
*
|
352
|
+
* call-seq:
|
353
|
+
* request.policy_id -> string or nil
|
354
|
+
*/
|
355
|
+
static VALUE
|
356
|
+
ossl_ts_req_get_policy_id(VALUE self)
|
357
|
+
{
|
358
|
+
TS_REQ *req;
|
359
|
+
|
360
|
+
GetTSRequest(self, req);
|
361
|
+
if (!TS_REQ_get_policy_id(req))
|
362
|
+
return Qnil;
|
363
|
+
return get_asn1obj(TS_REQ_get_policy_id(req));
|
364
|
+
}
|
365
|
+
|
366
|
+
/*
|
367
|
+
* Allows to set the object identifier that represents the
|
368
|
+
* timestamp policy under which the server shall create the timestamp. This
|
369
|
+
* may be left +nil+, implying that the timestamp server will issue the
|
370
|
+
* timestamp using some default policy.
|
371
|
+
*
|
372
|
+
* ===Example:
|
373
|
+
* request.policy_id = "1.2.3.4.5"
|
374
|
+
*
|
375
|
+
* call-seq:
|
376
|
+
* request.policy_id = "string" -> string
|
377
|
+
*/
|
378
|
+
static VALUE
|
379
|
+
ossl_ts_req_set_policy_id(VALUE self, VALUE oid)
|
380
|
+
{
|
381
|
+
TS_REQ *req;
|
382
|
+
ASN1_OBJECT *obj;
|
383
|
+
int ok;
|
384
|
+
|
385
|
+
GetTSRequest(self, req);
|
386
|
+
obj = obj_to_asn1obj(oid);
|
387
|
+
ok = TS_REQ_set_policy_id(req, obj);
|
388
|
+
ASN1_OBJECT_free(obj);
|
389
|
+
if (!ok)
|
390
|
+
ossl_raise(eTimestampError, "TS_REQ_set_policy_id");
|
391
|
+
|
392
|
+
return oid;
|
393
|
+
}
|
394
|
+
|
395
|
+
/*
|
396
|
+
* Returns the nonce (number used once) that the server shall include in its
|
397
|
+
* response.
|
398
|
+
*
|
399
|
+
* call-seq:
|
400
|
+
* request.nonce -> BN or nil
|
401
|
+
*/
|
402
|
+
static VALUE
|
403
|
+
ossl_ts_req_get_nonce(VALUE self)
|
404
|
+
{
|
405
|
+
TS_REQ *req;
|
406
|
+
const ASN1_INTEGER * nonce;
|
407
|
+
|
408
|
+
GetTSRequest(self, req);
|
409
|
+
if (!(nonce = TS_REQ_get_nonce(req)))
|
410
|
+
return Qnil;
|
411
|
+
return asn1integer_to_num(nonce);
|
412
|
+
}
|
413
|
+
|
414
|
+
/*
|
415
|
+
* Sets the nonce (number used once) that the server shall include in its
|
416
|
+
* response. If the nonce is set, the server must return the same nonce value in
|
417
|
+
* a valid Response.
|
418
|
+
*
|
419
|
+
* call-seq:
|
420
|
+
* request.nonce = number -> BN
|
421
|
+
*/
|
422
|
+
static VALUE
|
423
|
+
ossl_ts_req_set_nonce(VALUE self, VALUE num)
|
424
|
+
{
|
425
|
+
TS_REQ *req;
|
426
|
+
ASN1_INTEGER *nonce;
|
427
|
+
int ok;
|
428
|
+
|
429
|
+
GetTSRequest(self, req);
|
430
|
+
nonce = num_to_asn1integer(num, NULL);
|
431
|
+
ok = TS_REQ_set_nonce(req, nonce);
|
432
|
+
ASN1_INTEGER_free(nonce);
|
433
|
+
if (!ok)
|
434
|
+
ossl_raise(eTimestampError, NULL);
|
435
|
+
return num;
|
436
|
+
}
|
437
|
+
|
438
|
+
/*
|
439
|
+
* Indicates whether the response shall contain the timestamp authority's
|
440
|
+
* certificate or not.
|
441
|
+
*
|
442
|
+
* call-seq:
|
443
|
+
* request.cert_requested? -> true or false
|
444
|
+
*/
|
445
|
+
static VALUE
|
446
|
+
ossl_ts_req_get_cert_requested(VALUE self)
|
447
|
+
{
|
448
|
+
TS_REQ *req;
|
449
|
+
|
450
|
+
GetTSRequest(self, req);
|
451
|
+
return TS_REQ_get_cert_req(req) ? Qtrue: Qfalse;
|
452
|
+
}
|
453
|
+
|
454
|
+
/*
|
455
|
+
* Specify whether the response shall contain the timestamp authority's
|
456
|
+
* certificate or not. The default value is +true+.
|
457
|
+
*
|
458
|
+
* call-seq:
|
459
|
+
* request.cert_requested = boolean -> true or false
|
460
|
+
*/
|
461
|
+
static VALUE
|
462
|
+
ossl_ts_req_set_cert_requested(VALUE self, VALUE requested)
|
463
|
+
{
|
464
|
+
TS_REQ *req;
|
465
|
+
|
466
|
+
GetTSRequest(self, req);
|
467
|
+
TS_REQ_set_cert_req(req, RTEST(requested));
|
468
|
+
|
469
|
+
return requested;
|
470
|
+
}
|
471
|
+
|
472
|
+
/*
|
473
|
+
* DER-encodes this Request.
|
474
|
+
*
|
475
|
+
* call-seq:
|
476
|
+
* request.to_der -> DER-encoded string
|
477
|
+
*/
|
478
|
+
static VALUE
|
479
|
+
ossl_ts_req_to_der(VALUE self)
|
480
|
+
{
|
481
|
+
TS_REQ *req;
|
482
|
+
TS_MSG_IMPRINT *mi;
|
483
|
+
X509_ALGOR *algo;
|
484
|
+
ASN1_OCTET_STRING *hashed_msg;
|
485
|
+
|
486
|
+
GetTSRequest(self, req);
|
487
|
+
mi = TS_REQ_get_msg_imprint(req);
|
488
|
+
|
489
|
+
algo = TS_MSG_IMPRINT_get_algo(mi);
|
490
|
+
if (OBJ_obj2nid(algo->algorithm) == NID_undef)
|
491
|
+
ossl_raise(eTimestampError, "Message imprint missing algorithm");
|
492
|
+
|
493
|
+
hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
|
494
|
+
if (!hashed_msg->length)
|
495
|
+
ossl_raise(eTimestampError, "Message imprint missing hashed message");
|
496
|
+
|
497
|
+
return asn1_to_der((void *)req, (int (*)(void *, unsigned char **))i2d_TS_REQ);
|
498
|
+
}
|
499
|
+
|
500
|
+
static VALUE
|
501
|
+
ossl_ts_resp_alloc(VALUE klass)
|
502
|
+
{
|
503
|
+
TS_RESP *resp;
|
504
|
+
VALUE obj;
|
505
|
+
|
506
|
+
obj = NewTSResponse(klass);
|
507
|
+
if (!(resp = TS_RESP_new()))
|
508
|
+
ossl_raise(eTimestampError, NULL);
|
509
|
+
SetTSResponse(obj, resp);
|
510
|
+
|
511
|
+
return obj;
|
512
|
+
}
|
513
|
+
|
514
|
+
/*
|
515
|
+
* Creates a Response from a +File+ or +string+ parameter, the
|
516
|
+
* corresponding +File+ or +string+ must be DER-encoded. Please note
|
517
|
+
* that Response is an immutable read-only class. If you'd like to create
|
518
|
+
* timestamps please refer to Factory instead.
|
519
|
+
*
|
520
|
+
* call-seq:
|
521
|
+
* OpenSSL::Timestamp::Response.new(file) -> response
|
522
|
+
* OpenSSL::Timestamp::Response.new(string) -> response
|
523
|
+
*/
|
524
|
+
static VALUE
|
525
|
+
ossl_ts_resp_initialize(VALUE self, VALUE der)
|
526
|
+
{
|
527
|
+
TS_RESP *ts_resp = DATA_PTR(self);
|
528
|
+
BIO *in;
|
529
|
+
|
530
|
+
der = ossl_to_der_if_possible(der);
|
531
|
+
in = ossl_obj2bio(&der);
|
532
|
+
ts_resp = d2i_TS_RESP_bio(in, &ts_resp);
|
533
|
+
BIO_free(in);
|
534
|
+
if (!ts_resp) {
|
535
|
+
DATA_PTR(self) = NULL;
|
536
|
+
ossl_raise(eTimestampError, "Error when decoding the timestamp response");
|
537
|
+
}
|
538
|
+
DATA_PTR(self) = ts_resp;
|
539
|
+
|
540
|
+
return self;
|
541
|
+
}
|
542
|
+
|
543
|
+
/*
|
544
|
+
* Returns one of GRANTED, GRANTED_WITH_MODS, REJECTION, WAITING,
|
545
|
+
* REVOCATION_WARNING or REVOCATION_NOTIFICATION. A timestamp token has
|
546
|
+
* been created only in case +status+ is equal to GRANTED or GRANTED_WITH_MODS.
|
547
|
+
*
|
548
|
+
* call-seq:
|
549
|
+
* response.status -> BN (never nil)
|
550
|
+
*/
|
551
|
+
static VALUE
|
552
|
+
ossl_ts_resp_get_status(VALUE self)
|
553
|
+
{
|
554
|
+
TS_RESP *resp;
|
555
|
+
TS_STATUS_INFO *si;
|
556
|
+
const ASN1_INTEGER *st;
|
557
|
+
|
558
|
+
GetTSResponse(self, resp);
|
559
|
+
si = TS_RESP_get_status_info(resp);
|
560
|
+
st = TS_STATUS_INFO_get0_status(si);
|
561
|
+
|
562
|
+
return asn1integer_to_num(st);
|
563
|
+
}
|
564
|
+
|
565
|
+
/*
|
566
|
+
* In cases no timestamp token has been created, this field contains further
|
567
|
+
* info about the reason why response creation failed. The method returns either
|
568
|
+
* nil (the request was successful and a timestamp token was created) or one of
|
569
|
+
* the following:
|
570
|
+
* * :BAD_ALG - Indicates that the timestamp server rejects the message
|
571
|
+
* imprint algorithm used in the Request
|
572
|
+
* * :BAD_REQUEST - Indicates that the timestamp server was not able to process
|
573
|
+
* the Request properly
|
574
|
+
* * :BAD_DATA_FORMAT - Indicates that the timestamp server was not able to
|
575
|
+
* parse certain data in the Request
|
576
|
+
* * :TIME_NOT_AVAILABLE - Indicates that the server could not access its time
|
577
|
+
* source
|
578
|
+
* * :UNACCEPTED_POLICY - Indicates that the requested policy identifier is not
|
579
|
+
* recognized or supported by the timestamp server
|
580
|
+
* * :UNACCEPTED_EXTENSIION - Indicates that an extension in the Request is
|
581
|
+
* not supported by the timestamp server
|
582
|
+
* * :ADD_INFO_NOT_AVAILABLE -Indicates that additional information requested
|
583
|
+
* is either not understood or currently not available
|
584
|
+
* * :SYSTEM_FAILURE - Timestamp creation failed due to an internal error that
|
585
|
+
* occurred on the timestamp server
|
586
|
+
*
|
587
|
+
* call-seq:
|
588
|
+
* response.failure_info -> nil or symbol
|
589
|
+
*/
|
590
|
+
static VALUE
|
591
|
+
ossl_ts_resp_get_failure_info(VALUE self)
|
592
|
+
{
|
593
|
+
TS_RESP *resp;
|
594
|
+
TS_STATUS_INFO *si;
|
595
|
+
|
596
|
+
/* The ASN1_BIT_STRING_get_bit changed from 1.0.0. to 1.1.0, making this
|
597
|
+
* const. */
|
598
|
+
#if defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO)
|
599
|
+
const ASN1_BIT_STRING *fi;
|
600
|
+
#else
|
601
|
+
ASN1_BIT_STRING *fi;
|
602
|
+
#endif
|
603
|
+
|
604
|
+
GetTSResponse(self, resp);
|
605
|
+
si = TS_RESP_get_status_info(resp);
|
606
|
+
fi = TS_STATUS_INFO_get0_failure_info(si);
|
607
|
+
if (!fi)
|
608
|
+
return Qnil;
|
609
|
+
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_ALG))
|
610
|
+
return sBAD_ALG;
|
611
|
+
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_REQUEST))
|
612
|
+
return sBAD_REQUEST;
|
613
|
+
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_DATA_FORMAT))
|
614
|
+
return sBAD_DATA_FORMAT;
|
615
|
+
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_TIME_NOT_AVAILABLE))
|
616
|
+
return sTIME_NOT_AVAILABLE;
|
617
|
+
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_POLICY))
|
618
|
+
return sUNACCEPTED_POLICY;
|
619
|
+
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_EXTENSION))
|
620
|
+
return sUNACCEPTED_EXTENSION;
|
621
|
+
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_ADD_INFO_NOT_AVAILABLE))
|
622
|
+
return sADD_INFO_NOT_AVAILABLE;
|
623
|
+
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_SYSTEM_FAILURE))
|
624
|
+
return sSYSTEM_FAILURE;
|
625
|
+
|
626
|
+
ossl_raise(eTimestampError, "Unrecognized failure info.");
|
627
|
+
}
|
628
|
+
|
629
|
+
/*
|
630
|
+
* In cases of failure this field may contain an array of strings further
|
631
|
+
* describing the origin of the failure.
|
632
|
+
*
|
633
|
+
* call-seq:
|
634
|
+
* response.status_text -> Array of strings or nil
|
635
|
+
*/
|
636
|
+
static VALUE
|
637
|
+
ossl_ts_resp_get_status_text(VALUE self)
|
638
|
+
{
|
639
|
+
TS_RESP *resp;
|
640
|
+
TS_STATUS_INFO *si;
|
641
|
+
const STACK_OF(ASN1_UTF8STRING) *text;
|
642
|
+
ASN1_UTF8STRING *current;
|
643
|
+
int i;
|
644
|
+
VALUE ret = rb_ary_new();
|
645
|
+
|
646
|
+
GetTSResponse(self, resp);
|
647
|
+
si = TS_RESP_get_status_info(resp);
|
648
|
+
if ((text = TS_STATUS_INFO_get0_text(si))) {
|
649
|
+
for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
|
650
|
+
current = sk_ASN1_UTF8STRING_value(text, i);
|
651
|
+
rb_ary_push(ret, asn1str_to_str(current));
|
652
|
+
}
|
653
|
+
}
|
654
|
+
|
655
|
+
return ret;
|
656
|
+
}
|
657
|
+
|
658
|
+
/*
|
659
|
+
* If a timestamp token is present, this returns it in the form of a
|
660
|
+
* OpenSSL::PKCS7.
|
661
|
+
*
|
662
|
+
* call-seq:
|
663
|
+
* response.token -> nil or OpenSSL::PKCS7
|
664
|
+
*/
|
665
|
+
static VALUE
|
666
|
+
ossl_ts_resp_get_token(VALUE self)
|
667
|
+
{
|
668
|
+
TS_RESP *resp;
|
669
|
+
PKCS7 *p7, *copy;
|
670
|
+
VALUE obj;
|
671
|
+
|
672
|
+
GetTSResponse(self, resp);
|
673
|
+
if (!(p7 = TS_RESP_get_token(resp)))
|
674
|
+
return Qnil;
|
675
|
+
|
676
|
+
obj = NewPKCS7(cPKCS7);
|
677
|
+
|
678
|
+
if (!(copy = PKCS7_dup(p7)))
|
679
|
+
ossl_raise(eTimestampError, NULL);
|
680
|
+
|
681
|
+
SetPKCS7(obj, copy);
|
682
|
+
|
683
|
+
return obj;
|
684
|
+
}
|
685
|
+
|
686
|
+
/*
|
687
|
+
* Get the response's token info if present.
|
688
|
+
*
|
689
|
+
* call-seq:
|
690
|
+
* response.token_info -> nil or OpenSSL::Timestamp::TokenInfo
|
691
|
+
*/
|
692
|
+
static VALUE
|
693
|
+
ossl_ts_resp_get_token_info(VALUE self)
|
694
|
+
{
|
695
|
+
TS_RESP *resp;
|
696
|
+
TS_TST_INFO *info, *copy;
|
697
|
+
VALUE obj;
|
698
|
+
|
699
|
+
GetTSResponse(self, resp);
|
700
|
+
if (!(info = TS_RESP_get_tst_info(resp)))
|
701
|
+
return Qnil;
|
702
|
+
|
703
|
+
obj = NewTSTokenInfo(cTimestampTokenInfo);
|
704
|
+
|
705
|
+
if (!(copy = TS_TST_INFO_dup(info)))
|
706
|
+
ossl_raise(eTimestampError, NULL);
|
707
|
+
|
708
|
+
SetTSTokenInfo(obj, copy);
|
709
|
+
|
710
|
+
return obj;
|
711
|
+
}
|
712
|
+
|
713
|
+
/*
|
714
|
+
* If the Request specified to request the TSA certificate
|
715
|
+
* (Request#cert_requested = true), then this field contains the
|
716
|
+
* certificate of the timestamp authority.
|
717
|
+
*
|
718
|
+
* call-seq:
|
719
|
+
* response.tsa_certificate -> OpenSSL::X509::Certificate or nil
|
720
|
+
*/
|
721
|
+
static VALUE
|
722
|
+
ossl_ts_resp_get_tsa_certificate(VALUE self)
|
723
|
+
{
|
724
|
+
TS_RESP *resp;
|
725
|
+
PKCS7 *p7;
|
726
|
+
PKCS7_SIGNER_INFO *ts_info;
|
727
|
+
X509 *cert;
|
728
|
+
|
729
|
+
GetTSResponse(self, resp);
|
730
|
+
if (!(p7 = TS_RESP_get_token(resp)))
|
731
|
+
return Qnil;
|
732
|
+
ts_info = sk_PKCS7_SIGNER_INFO_value(p7->d.sign->signer_info, 0);
|
733
|
+
cert = PKCS7_cert_from_signer_info(p7, ts_info);
|
734
|
+
if (!cert)
|
735
|
+
return Qnil;
|
736
|
+
return ossl_x509_new(cert);
|
737
|
+
}
|
738
|
+
|
739
|
+
/*
|
740
|
+
* Returns the Response in DER-encoded form.
|
741
|
+
*
|
742
|
+
* call-seq:
|
743
|
+
* response.to_der -> string
|
744
|
+
*/
|
745
|
+
static VALUE
|
746
|
+
ossl_ts_resp_to_der(VALUE self)
|
747
|
+
{
|
748
|
+
TS_RESP *resp;
|
749
|
+
|
750
|
+
GetTSResponse(self, resp);
|
751
|
+
return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP);
|
752
|
+
}
|
753
|
+
|
754
|
+
/*
|
755
|
+
* Verifies a timestamp token by checking the signature, validating the
|
756
|
+
* certificate chain implied by tsa_certificate and by checking conformance to
|
757
|
+
* a given Request. Mandatory parameters are the Request associated to this
|
758
|
+
* Response, and an OpenSSL::X509::Store of trusted roots.
|
759
|
+
*
|
760
|
+
* Intermediate certificates can optionally be supplied for creating the
|
761
|
+
* certificate chain. These intermediate certificates must all be
|
762
|
+
* instances of OpenSSL::X509::Certificate.
|
763
|
+
*
|
764
|
+
* If validation fails, several kinds of exceptions can be raised:
|
765
|
+
* * TypeError if types don't fit
|
766
|
+
* * TimestampError if something is wrong with the timestamp token itself, if
|
767
|
+
* it is not conformant to the Request, or if validation of the timestamp
|
768
|
+
* certificate chain fails.
|
769
|
+
*
|
770
|
+
* call-seq:
|
771
|
+
* response.verify(Request, root_store) -> Response
|
772
|
+
* response.verify(Request, root_store, [intermediate_cert]) -> Response
|
773
|
+
*/
|
774
|
+
static VALUE
|
775
|
+
ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self)
|
776
|
+
{
|
777
|
+
VALUE ts_req, store, intermediates;
|
778
|
+
TS_RESP *resp;
|
779
|
+
TS_REQ *req;
|
780
|
+
X509_STORE *x509st;
|
781
|
+
TS_VERIFY_CTX *ctx;
|
782
|
+
STACK_OF(X509) *x509inter = NULL;
|
783
|
+
PKCS7* p7;
|
784
|
+
X509 *cert;
|
785
|
+
int status, i, ok;
|
786
|
+
|
787
|
+
rb_scan_args(argc, argv, "21", &ts_req, &store, &intermediates);
|
788
|
+
|
789
|
+
GetTSResponse(self, resp);
|
790
|
+
GetTSRequest(ts_req, req);
|
791
|
+
x509st = GetX509StorePtr(store);
|
792
|
+
|
793
|
+
if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(req, NULL))) {
|
794
|
+
ossl_raise(eTimestampError, "Error when creating the verification context.");
|
795
|
+
}
|
796
|
+
|
797
|
+
if (!NIL_P(intermediates)) {
|
798
|
+
x509inter = ossl_protect_x509_ary2sk(intermediates, &status);
|
799
|
+
if (status) {
|
800
|
+
TS_VERIFY_CTX_free(ctx);
|
801
|
+
rb_jump_tag(status);
|
802
|
+
}
|
803
|
+
} else if (!(x509inter = sk_X509_new_null())) {
|
804
|
+
TS_VERIFY_CTX_free(ctx);
|
805
|
+
ossl_raise(eTimestampError, "sk_X509_new_null");
|
806
|
+
}
|
807
|
+
|
808
|
+
if (!(p7 = TS_RESP_get_token(resp))) {
|
809
|
+
TS_VERIFY_CTX_free(ctx);
|
810
|
+
sk_X509_pop_free(x509inter, X509_free);
|
811
|
+
ossl_raise(eTimestampError, "TS_RESP_get_token");
|
812
|
+
}
|
813
|
+
for (i=0; i < sk_X509_num(p7->d.sign->cert); i++) {
|
814
|
+
cert = sk_X509_value(p7->d.sign->cert, i);
|
815
|
+
if (!sk_X509_push(x509inter, cert)) {
|
816
|
+
sk_X509_pop_free(x509inter, X509_free);
|
817
|
+
TS_VERIFY_CTX_free(ctx);
|
818
|
+
ossl_raise(eTimestampError, "sk_X509_push");
|
819
|
+
}
|
820
|
+
X509_up_ref(cert);
|
821
|
+
}
|
822
|
+
|
823
|
+
TS_VERIFY_CTS_set_certs(ctx, x509inter);
|
824
|
+
TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
|
825
|
+
TS_VERIFY_CTX_set_store(ctx, x509st);
|
826
|
+
|
827
|
+
ok = TS_RESP_verify_response(ctx, resp);
|
828
|
+
|
829
|
+
/* WORKAROUND:
|
830
|
+
* X509_STORE can count references, but X509_STORE_free() doesn't check
|
831
|
+
* this. To prevent our X509_STORE from being freed with our
|
832
|
+
* TS_VERIFY_CTX we set the store to NULL first.
|
833
|
+
* Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2)
|
834
|
+
*/
|
835
|
+
TS_VERIFY_CTX_set_store(ctx, NULL);
|
836
|
+
TS_VERIFY_CTX_free(ctx);
|
837
|
+
|
838
|
+
if (!ok)
|
839
|
+
ossl_raise(eTimestampError, "TS_RESP_verify_response");
|
840
|
+
|
841
|
+
return self;
|
842
|
+
}
|
843
|
+
|
844
|
+
static VALUE
|
845
|
+
ossl_ts_token_info_alloc(VALUE klass)
|
846
|
+
{
|
847
|
+
TS_TST_INFO *info;
|
848
|
+
VALUE obj;
|
849
|
+
|
850
|
+
obj = NewTSTokenInfo(klass);
|
851
|
+
if (!(info = TS_TST_INFO_new()))
|
852
|
+
ossl_raise(eTimestampError, NULL);
|
853
|
+
SetTSTokenInfo(obj, info);
|
854
|
+
|
855
|
+
return obj;
|
856
|
+
}
|
857
|
+
|
858
|
+
/*
|
859
|
+
* Creates a TokenInfo from a +File+ or +string+ parameter, the
|
860
|
+
* corresponding +File+ or +string+ must be DER-encoded. Please note
|
861
|
+
* that TokenInfo is an immutable read-only class. If you'd like to create
|
862
|
+
* timestamps please refer to Factory instead.
|
863
|
+
*
|
864
|
+
* call-seq:
|
865
|
+
* OpenSSL::Timestamp::TokenInfo.new(file) -> token-info
|
866
|
+
* OpenSSL::Timestamp::TokenInfo.new(string) -> token-info
|
867
|
+
*/
|
868
|
+
static VALUE
|
869
|
+
ossl_ts_token_info_initialize(VALUE self, VALUE der)
|
870
|
+
{
|
871
|
+
TS_TST_INFO *info = DATA_PTR(self);
|
872
|
+
BIO *in;
|
873
|
+
|
874
|
+
der = ossl_to_der_if_possible(der);
|
875
|
+
in = ossl_obj2bio(&der);
|
876
|
+
info = d2i_TS_TST_INFO_bio(in, &info);
|
877
|
+
BIO_free(in);
|
878
|
+
if (!info) {
|
879
|
+
DATA_PTR(self) = NULL;
|
880
|
+
ossl_raise(eTimestampError, "Error when decoding the timestamp token info");
|
881
|
+
}
|
882
|
+
DATA_PTR(self) = info;
|
883
|
+
|
884
|
+
return self;
|
885
|
+
}
|
886
|
+
|
887
|
+
/*
|
888
|
+
* Returns the version number of the token info. With compliant servers,
|
889
|
+
* this value should be +1+ if present. If status is GRANTED or
|
890
|
+
* GRANTED_WITH_MODS.
|
891
|
+
*
|
892
|
+
* call-seq:
|
893
|
+
* token_info.version -> Integer or nil
|
894
|
+
*/
|
895
|
+
static VALUE
|
896
|
+
ossl_ts_token_info_get_version(VALUE self)
|
897
|
+
{
|
898
|
+
TS_TST_INFO *info;
|
899
|
+
|
900
|
+
GetTSTokenInfo(self, info);
|
901
|
+
return LONG2NUM(TS_TST_INFO_get_version(info));
|
902
|
+
}
|
903
|
+
|
904
|
+
/*
|
905
|
+
* Returns the timestamp policy object identifier of the policy this timestamp
|
906
|
+
* was created under. If status is GRANTED or GRANTED_WITH_MODS, this is never
|
907
|
+
* +nil+.
|
908
|
+
*
|
909
|
+
* ===Example:
|
910
|
+
* id = token_info.policy_id
|
911
|
+
* puts id -> "1.2.3.4.5"
|
912
|
+
*
|
913
|
+
* call-seq:
|
914
|
+
* token_info.policy_id -> string or nil
|
915
|
+
*/
|
916
|
+
static VALUE
|
917
|
+
ossl_ts_token_info_get_policy_id(VALUE self)
|
918
|
+
{
|
919
|
+
TS_TST_INFO *info;
|
920
|
+
|
921
|
+
GetTSTokenInfo(self, info);
|
922
|
+
return get_asn1obj(TS_TST_INFO_get_policy_id(info));
|
923
|
+
}
|
924
|
+
|
925
|
+
/*
|
926
|
+
* Returns the 'short name' of the object identifier representing the algorithm
|
927
|
+
* that was used to derive the message imprint digest. For valid timestamps,
|
928
|
+
* this is the same value that was already given in the Request. If status is
|
929
|
+
* GRANTED or GRANTED_WITH_MODS, this is never +nil+.
|
930
|
+
*
|
931
|
+
* ===Example:
|
932
|
+
* algo = token_info.algorithm
|
933
|
+
* puts algo -> "SHA1"
|
934
|
+
*
|
935
|
+
* call-seq:
|
936
|
+
* token_info.algorithm -> string or nil
|
937
|
+
*/
|
938
|
+
static VALUE
|
939
|
+
ossl_ts_token_info_get_algorithm(VALUE self)
|
940
|
+
{
|
941
|
+
TS_TST_INFO *info;
|
942
|
+
TS_MSG_IMPRINT *mi;
|
943
|
+
X509_ALGOR *algo;
|
944
|
+
|
945
|
+
GetTSTokenInfo(self, info);
|
946
|
+
mi = TS_TST_INFO_get_msg_imprint(info);
|
947
|
+
algo = TS_MSG_IMPRINT_get_algo(mi);
|
948
|
+
return get_asn1obj(algo->algorithm);
|
949
|
+
}
|
950
|
+
|
951
|
+
/*
|
952
|
+
* Returns the message imprint digest. For valid timestamps,
|
953
|
+
* this is the same value that was already given in the Request.
|
954
|
+
* If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+.
|
955
|
+
*
|
956
|
+
* ===Example:
|
957
|
+
* mi = token_info.msg_imprint
|
958
|
+
* puts mi -> "DEADBEEF"
|
959
|
+
*
|
960
|
+
* call-seq:
|
961
|
+
* token_info.msg_imprint -> string.
|
962
|
+
*/
|
963
|
+
static VALUE
|
964
|
+
ossl_ts_token_info_get_msg_imprint(VALUE self)
|
965
|
+
{
|
966
|
+
TS_TST_INFO *info;
|
967
|
+
TS_MSG_IMPRINT *mi;
|
968
|
+
ASN1_OCTET_STRING *hashed_msg;
|
969
|
+
VALUE ret;
|
970
|
+
|
971
|
+
GetTSTokenInfo(self, info);
|
972
|
+
mi = TS_TST_INFO_get_msg_imprint(info);
|
973
|
+
hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
|
974
|
+
ret = rb_str_new((const char *)hashed_msg->data, hashed_msg->length);
|
975
|
+
|
976
|
+
return ret;
|
977
|
+
}
|
978
|
+
|
979
|
+
/*
|
980
|
+
* Returns serial number of the timestamp token. This value shall never be the
|
981
|
+
* same for two timestamp tokens issued by a dedicated timestamp authority.
|
982
|
+
* If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+.
|
983
|
+
*
|
984
|
+
* call-seq:
|
985
|
+
* token_info.serial_number -> BN or nil
|
986
|
+
*/
|
987
|
+
static VALUE
|
988
|
+
ossl_ts_token_info_get_serial_number(VALUE self)
|
989
|
+
{
|
990
|
+
TS_TST_INFO *info;
|
991
|
+
|
992
|
+
GetTSTokenInfo(self, info);
|
993
|
+
return asn1integer_to_num(TS_TST_INFO_get_serial(info));
|
994
|
+
}
|
995
|
+
|
996
|
+
/*
|
997
|
+
* Returns time when this timestamp token was created. If status is GRANTED or
|
998
|
+
* GRANTED_WITH_MODS, this is never +nil+.
|
999
|
+
*
|
1000
|
+
* call-seq:
|
1001
|
+
* token_info.gen_time -> Time
|
1002
|
+
*/
|
1003
|
+
static VALUE
|
1004
|
+
ossl_ts_token_info_get_gen_time(VALUE self)
|
1005
|
+
{
|
1006
|
+
TS_TST_INFO *info;
|
1007
|
+
|
1008
|
+
GetTSTokenInfo(self, info);
|
1009
|
+
return asn1time_to_time(TS_TST_INFO_get_time(info));
|
1010
|
+
}
|
1011
|
+
|
1012
|
+
/*
|
1013
|
+
* If the ordering field is missing, or if the ordering field is present
|
1014
|
+
* and set to false, then the genTime field only indicates the time at
|
1015
|
+
* which the time-stamp token has been created by the TSA. In such a
|
1016
|
+
* case, the ordering of time-stamp tokens issued by the same TSA or
|
1017
|
+
* different TSAs is only possible when the difference between the
|
1018
|
+
* genTime of the first time-stamp token and the genTime of the second
|
1019
|
+
* time-stamp token is greater than the sum of the accuracies of the
|
1020
|
+
* genTime for each time-stamp token.
|
1021
|
+
*
|
1022
|
+
* If the ordering field is present and set to true, every time-stamp
|
1023
|
+
* token from the same TSA can always be ordered based on the genTime
|
1024
|
+
* field, regardless of the genTime accuracy.
|
1025
|
+
*
|
1026
|
+
* call-seq:
|
1027
|
+
* token_info.ordering -> true, falses or nil
|
1028
|
+
*/
|
1029
|
+
static VALUE
|
1030
|
+
ossl_ts_token_info_get_ordering(VALUE self)
|
1031
|
+
{
|
1032
|
+
TS_TST_INFO *info;
|
1033
|
+
|
1034
|
+
GetTSTokenInfo(self, info);
|
1035
|
+
return TS_TST_INFO_get_ordering(info) ? Qtrue : Qfalse;
|
1036
|
+
}
|
1037
|
+
|
1038
|
+
/*
|
1039
|
+
* If the timestamp token is valid then this field contains the same nonce that
|
1040
|
+
* was passed to the timestamp server in the initial Request.
|
1041
|
+
*
|
1042
|
+
* call-seq:
|
1043
|
+
* token_info.nonce -> BN or nil
|
1044
|
+
*/
|
1045
|
+
static VALUE
|
1046
|
+
ossl_ts_token_info_get_nonce(VALUE self)
|
1047
|
+
{
|
1048
|
+
TS_TST_INFO *info;
|
1049
|
+
const ASN1_INTEGER *nonce;
|
1050
|
+
|
1051
|
+
GetTSTokenInfo(self, info);
|
1052
|
+
if (!(nonce = TS_TST_INFO_get_nonce(info)))
|
1053
|
+
return Qnil;
|
1054
|
+
|
1055
|
+
return asn1integer_to_num(nonce);
|
1056
|
+
}
|
1057
|
+
|
1058
|
+
/*
|
1059
|
+
* Returns the TokenInfo in DER-encoded form.
|
1060
|
+
*
|
1061
|
+
* call-seq:
|
1062
|
+
* token_info.to_der -> string
|
1063
|
+
*/
|
1064
|
+
static VALUE
|
1065
|
+
ossl_ts_token_info_to_der(VALUE self)
|
1066
|
+
{
|
1067
|
+
TS_TST_INFO *info;
|
1068
|
+
|
1069
|
+
GetTSTokenInfo(self, info);
|
1070
|
+
return asn1_to_der((void *)info, (int (*)(void *, unsigned char **))i2d_TS_TST_INFO);
|
1071
|
+
}
|
1072
|
+
|
1073
|
+
static ASN1_INTEGER *
|
1074
|
+
ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data)
|
1075
|
+
{
|
1076
|
+
ASN1_INTEGER **snptr = (ASN1_INTEGER **)data;
|
1077
|
+
ASN1_INTEGER *sn = *snptr;
|
1078
|
+
*snptr = NULL;
|
1079
|
+
return sn;
|
1080
|
+
}
|
1081
|
+
|
1082
|
+
static int
|
1083
|
+
#if !defined(LIBRESSL_VERSION_NUMBER)
|
1084
|
+
ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec)
|
1085
|
+
#else
|
1086
|
+
ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec)
|
1087
|
+
#endif
|
1088
|
+
{
|
1089
|
+
*sec = *((long *)data);
|
1090
|
+
*usec = 0;
|
1091
|
+
return 1;
|
1092
|
+
}
|
1093
|
+
|
1094
|
+
/*
|
1095
|
+
* Creates a Response with the help of an OpenSSL::PKey, an
|
1096
|
+
* OpenSSL::X509::Certificate and a Request.
|
1097
|
+
*
|
1098
|
+
* Mandatory parameters for timestamp creation that need to be set in the
|
1099
|
+
* Request:
|
1100
|
+
*
|
1101
|
+
* * Request#algorithm
|
1102
|
+
* * Request#message_imprint
|
1103
|
+
*
|
1104
|
+
* Mandatory parameters that need to be set in the Factory:
|
1105
|
+
* * Factory#serial_number
|
1106
|
+
* * Factory#gen_time
|
1107
|
+
* * Factory#allowed_digests
|
1108
|
+
*
|
1109
|
+
* In addition one of either Request#policy_id or Factory#default_policy_id
|
1110
|
+
* must be set.
|
1111
|
+
*
|
1112
|
+
* Raises a TimestampError if creation fails, though successfully created error
|
1113
|
+
* responses may be returned.
|
1114
|
+
*
|
1115
|
+
* call-seq:
|
1116
|
+
* factory.create_timestamp(key, certificate, request) -> Response
|
1117
|
+
*/
|
1118
|
+
static VALUE
|
1119
|
+
ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
|
1120
|
+
{
|
1121
|
+
VALUE serial_number, def_policy_id, gen_time, additional_certs, allowed_digests;
|
1122
|
+
VALUE str;
|
1123
|
+
STACK_OF(X509) *inter_certs;
|
1124
|
+
VALUE tsresp, ret = Qnil;
|
1125
|
+
EVP_PKEY *sign_key;
|
1126
|
+
X509 *tsa_cert;
|
1127
|
+
TS_REQ *req;
|
1128
|
+
TS_RESP *response = NULL;
|
1129
|
+
TS_RESP_CTX *ctx = NULL;
|
1130
|
+
BIO *req_bio;
|
1131
|
+
ASN1_INTEGER *asn1_serial = NULL;
|
1132
|
+
ASN1_OBJECT *def_policy_id_obj = NULL;
|
1133
|
+
long lgen_time;
|
1134
|
+
const char * err_msg = NULL;
|
1135
|
+
int status = 0;
|
1136
|
+
|
1137
|
+
tsresp = NewTSResponse(cTimestampResponse);
|
1138
|
+
tsa_cert = GetX509CertPtr(certificate);
|
1139
|
+
sign_key = GetPrivPKeyPtr(key);
|
1140
|
+
GetTSRequest(request, req);
|
1141
|
+
|
1142
|
+
gen_time = ossl_tsfac_get_gen_time(self);
|
1143
|
+
if (!rb_obj_is_instance_of(gen_time, rb_cTime)) {
|
1144
|
+
err_msg = "@gen_time must be a Time.";
|
1145
|
+
goto end;
|
1146
|
+
}
|
1147
|
+
lgen_time = NUM2LONG(rb_funcall(gen_time, rb_intern("to_i"), 0));
|
1148
|
+
|
1149
|
+
serial_number = ossl_tsfac_get_serial_number(self);
|
1150
|
+
if (NIL_P(serial_number)) {
|
1151
|
+
err_msg = "@serial_number must be set.";
|
1152
|
+
goto end;
|
1153
|
+
}
|
1154
|
+
asn1_serial = num_to_asn1integer(serial_number, NULL);
|
1155
|
+
|
1156
|
+
def_policy_id = ossl_tsfac_get_default_policy_id(self);
|
1157
|
+
if (NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
|
1158
|
+
err_msg = "No policy id in the request and no default policy set";
|
1159
|
+
goto end;
|
1160
|
+
}
|
1161
|
+
if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
|
1162
|
+
def_policy_id_obj = (ASN1_OBJECT*)rb_protect((VALUE (*)(VALUE))obj_to_asn1obj, (VALUE)def_policy_id, &status);
|
1163
|
+
if (status)
|
1164
|
+
goto end;
|
1165
|
+
}
|
1166
|
+
|
1167
|
+
if (!(ctx = TS_RESP_CTX_new())) {
|
1168
|
+
err_msg = "Memory allocation failed.";
|
1169
|
+
goto end;
|
1170
|
+
}
|
1171
|
+
|
1172
|
+
TS_RESP_CTX_set_serial_cb(ctx, ossl_tsfac_serial_cb, &asn1_serial);
|
1173
|
+
if (!TS_RESP_CTX_set_signer_cert(ctx, tsa_cert)) {
|
1174
|
+
err_msg = "Certificate does not contain the timestamping extension";
|
1175
|
+
goto end;
|
1176
|
+
}
|
1177
|
+
|
1178
|
+
additional_certs = ossl_tsfac_get_additional_certs(self);
|
1179
|
+
if (rb_obj_is_kind_of(additional_certs, rb_cArray)) {
|
1180
|
+
inter_certs = ossl_protect_x509_ary2sk(additional_certs, &status);
|
1181
|
+
if (status)
|
1182
|
+
goto end;
|
1183
|
+
|
1184
|
+
/* this dups the sk_X509 and ups each cert's ref count */
|
1185
|
+
TS_RESP_CTX_set_certs(ctx, inter_certs);
|
1186
|
+
sk_X509_pop_free(inter_certs, X509_free);
|
1187
|
+
}
|
1188
|
+
|
1189
|
+
TS_RESP_CTX_set_signer_key(ctx, sign_key);
|
1190
|
+
if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req))
|
1191
|
+
TS_RESP_CTX_set_def_policy(ctx, def_policy_id_obj);
|
1192
|
+
if (TS_REQ_get_policy_id(req))
|
1193
|
+
TS_RESP_CTX_set_def_policy(ctx, TS_REQ_get_policy_id(req));
|
1194
|
+
TS_RESP_CTX_set_time_cb(ctx, ossl_tsfac_time_cb, &lgen_time);
|
1195
|
+
|
1196
|
+
allowed_digests = ossl_tsfac_get_allowed_digests(self);
|
1197
|
+
if (rb_obj_is_kind_of(allowed_digests, rb_cArray)) {
|
1198
|
+
int i;
|
1199
|
+
VALUE rbmd;
|
1200
|
+
const EVP_MD *md;
|
1201
|
+
|
1202
|
+
for (i = 0; i < RARRAY_LEN(allowed_digests); i++) {
|
1203
|
+
rbmd = rb_ary_entry(allowed_digests, i);
|
1204
|
+
md = (const EVP_MD *)rb_protect((VALUE (*)(VALUE))ossl_evp_get_digestbyname, rbmd, &status);
|
1205
|
+
if (status)
|
1206
|
+
goto end;
|
1207
|
+
TS_RESP_CTX_add_md(ctx, md);
|
1208
|
+
}
|
1209
|
+
}
|
1210
|
+
|
1211
|
+
str = rb_protect(ossl_to_der, request, &status);
|
1212
|
+
if (status)
|
1213
|
+
goto end;
|
1214
|
+
|
1215
|
+
req_bio = (BIO*)rb_protect((VALUE (*)(VALUE))ossl_obj2bio, (VALUE)&str, &status);
|
1216
|
+
if (status)
|
1217
|
+
goto end;
|
1218
|
+
|
1219
|
+
response = TS_RESP_create_response(ctx, req_bio);
|
1220
|
+
BIO_free(req_bio);
|
1221
|
+
|
1222
|
+
if (!response) {
|
1223
|
+
err_msg = "Error during response generation";
|
1224
|
+
goto end;
|
1225
|
+
}
|
1226
|
+
|
1227
|
+
/* bad responses aren't exceptional, but openssl still sets error
|
1228
|
+
* information. */
|
1229
|
+
ossl_clear_error();
|
1230
|
+
|
1231
|
+
SetTSResponse(tsresp, response);
|
1232
|
+
ret = tsresp;
|
1233
|
+
|
1234
|
+
end:
|
1235
|
+
ASN1_INTEGER_free(asn1_serial);
|
1236
|
+
ASN1_OBJECT_free(def_policy_id_obj);
|
1237
|
+
TS_RESP_CTX_free(ctx);
|
1238
|
+
if (err_msg)
|
1239
|
+
ossl_raise(eTimestampError, err_msg);
|
1240
|
+
if (status)
|
1241
|
+
rb_jump_tag(status);
|
1242
|
+
return ret;
|
1243
|
+
}
|
1244
|
+
|
1245
|
+
/*
|
1246
|
+
* INIT
|
1247
|
+
*/
|
1248
|
+
void
|
1249
|
+
Init_ossl_ts(void)
|
1250
|
+
{
|
1251
|
+
#if 0
|
1252
|
+
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
1253
|
+
#endif
|
1254
|
+
|
1255
|
+
/*
|
1256
|
+
* Possible return value for +Response#failure_info+. Indicates that the
|
1257
|
+
* timestamp server rejects the message imprint algorithm used in the
|
1258
|
+
* +Request+
|
1259
|
+
*/
|
1260
|
+
sBAD_ALG = ID2SYM(rb_intern_const("BAD_ALG"));
|
1261
|
+
|
1262
|
+
/*
|
1263
|
+
* Possible return value for +Response#failure_info+. Indicates that the
|
1264
|
+
* timestamp server was not able to process the +Request+ properly.
|
1265
|
+
*/
|
1266
|
+
sBAD_REQUEST = ID2SYM(rb_intern_const("BAD_REQUEST"));
|
1267
|
+
/*
|
1268
|
+
* Possible return value for +Response#failure_info+. Indicates that the
|
1269
|
+
* timestamp server was not able to parse certain data in the +Request+.
|
1270
|
+
*/
|
1271
|
+
sBAD_DATA_FORMAT = ID2SYM(rb_intern_const("BAD_DATA_FORMAT"));
|
1272
|
+
|
1273
|
+
sTIME_NOT_AVAILABLE = ID2SYM(rb_intern_const("TIME_NOT_AVAILABLE"));
|
1274
|
+
sUNACCEPTED_POLICY = ID2SYM(rb_intern_const("UNACCEPTED_POLICY"));
|
1275
|
+
sUNACCEPTED_EXTENSION = ID2SYM(rb_intern_const("UNACCEPTED_EXTENSION"));
|
1276
|
+
sADD_INFO_NOT_AVAILABLE = ID2SYM(rb_intern_const("ADD_INFO_NOT_AVAILABLE"));
|
1277
|
+
sSYSTEM_FAILURE = ID2SYM(rb_intern_const("SYSTEM_FAILURE"));
|
1278
|
+
|
1279
|
+
/* Document-class: OpenSSL::Timestamp
|
1280
|
+
* Provides classes and methods to request, create and validate
|
1281
|
+
* {RFC3161-compliant}[http://www.ietf.org/rfc/rfc3161.txt] timestamps.
|
1282
|
+
* Request may be used to either create requests from scratch or to parse
|
1283
|
+
* existing requests that again can be used to request timestamps from a
|
1284
|
+
* timestamp server, e.g. via the net/http. The resulting timestamp
|
1285
|
+
* response may be parsed using Response.
|
1286
|
+
*
|
1287
|
+
* Please note that Response is read-only and immutable. To create a
|
1288
|
+
* Response, an instance of Factory as well as a valid Request are needed.
|
1289
|
+
*
|
1290
|
+
* ===Create a Response:
|
1291
|
+
* #Assumes ts.p12 is a PKCS#12-compatible file with a private key
|
1292
|
+
* #and a certificate that has an extended key usage of 'timeStamping'
|
1293
|
+
* p12 = OpenSSL::PKCS12.new(File.open('ts.p12', 'rb'), 'pwd')
|
1294
|
+
* md = OpenSSL::Digest.new('SHA1')
|
1295
|
+
* hash = md.digest(data) #some binary data to be timestamped
|
1296
|
+
* req = OpenSSL::Timestamp::Request.new
|
1297
|
+
* req.algorithm = 'SHA1'
|
1298
|
+
* req.message_imprint = hash
|
1299
|
+
* req.policy_id = "1.2.3.4.5"
|
1300
|
+
* req.nonce = 42
|
1301
|
+
* fac = OpenSSL::Timestamp::Factory.new
|
1302
|
+
* fac.gen_time = Time.now
|
1303
|
+
* fac.serial_number = 1
|
1304
|
+
* timestamp = fac.create_timestamp(p12.key, p12.certificate, req)
|
1305
|
+
*
|
1306
|
+
* ===Verify a timestamp response:
|
1307
|
+
* #Assume we have a timestamp token in a file called ts.der
|
1308
|
+
* ts = OpenSSL::Timestamp::Response.new(File.open('ts.der', 'rb')
|
1309
|
+
* #Assume we have the Request for this token in a file called req.der
|
1310
|
+
* req = OpenSSL::Timestamp::Request.new(File.open('req.der', 'rb')
|
1311
|
+
* # Assume the associated root CA certificate is contained in a
|
1312
|
+
* # DER-encoded file named root.cer
|
1313
|
+
* root = OpenSSL::X509::Certificate.new(File.open('root.cer', 'rb')
|
1314
|
+
* # get the necessary intermediate certificates, available in
|
1315
|
+
* # DER-encoded form in inter1.cer and inter2.cer
|
1316
|
+
* inter1 = OpenSSL::X509::Certificate.new(File.open('inter1.cer', 'rb')
|
1317
|
+
* inter2 = OpenSSL::X509::Certificate.new(File.open('inter2.cer', 'rb')
|
1318
|
+
* ts.verify(req, root, inter1, inter2) -> ts or raises an exception if validation fails
|
1319
|
+
*
|
1320
|
+
*/
|
1321
|
+
mTimestamp = rb_define_module_under(mOSSL, "Timestamp");
|
1322
|
+
|
1323
|
+
/* Document-class: OpenSSL::Timestamp::TimestampError
|
1324
|
+
* Generic exception class of the Timestamp module.
|
1325
|
+
*/
|
1326
|
+
eTimestampError = rb_define_class_under(mTimestamp, "TimestampError", eOSSLError);
|
1327
|
+
|
1328
|
+
/* Document-class: OpenSSL::Timestamp::Response
|
1329
|
+
* Immutable and read-only representation of a timestamp response returned
|
1330
|
+
* from a timestamp server after receiving an associated Request. Allows
|
1331
|
+
* access to specific information about the response but also allows to
|
1332
|
+
* verify the Response.
|
1333
|
+
*/
|
1334
|
+
cTimestampResponse = rb_define_class_under(mTimestamp, "Response", rb_cObject);
|
1335
|
+
rb_define_alloc_func(cTimestampResponse, ossl_ts_resp_alloc);
|
1336
|
+
rb_define_method(cTimestampResponse, "initialize", ossl_ts_resp_initialize, 1);
|
1337
|
+
rb_define_method(cTimestampResponse, "status", ossl_ts_resp_get_status, 0);
|
1338
|
+
rb_define_method(cTimestampResponse, "failure_info", ossl_ts_resp_get_failure_info, 0);
|
1339
|
+
rb_define_method(cTimestampResponse, "status_text", ossl_ts_resp_get_status_text, 0);
|
1340
|
+
rb_define_method(cTimestampResponse, "token", ossl_ts_resp_get_token, 0);
|
1341
|
+
rb_define_method(cTimestampResponse, "token_info", ossl_ts_resp_get_token_info, 0);
|
1342
|
+
rb_define_method(cTimestampResponse, "tsa_certificate", ossl_ts_resp_get_tsa_certificate, 0);
|
1343
|
+
rb_define_method(cTimestampResponse, "to_der", ossl_ts_resp_to_der, 0);
|
1344
|
+
rb_define_method(cTimestampResponse, "verify", ossl_ts_resp_verify, -1);
|
1345
|
+
|
1346
|
+
/* Document-class: OpenSSL::Timestamp::TokenInfo
|
1347
|
+
* Immutable and read-only representation of a timestamp token info from a
|
1348
|
+
* Response.
|
1349
|
+
*/
|
1350
|
+
cTimestampTokenInfo = rb_define_class_under(mTimestamp, "TokenInfo", rb_cObject);
|
1351
|
+
rb_define_alloc_func(cTimestampTokenInfo, ossl_ts_token_info_alloc);
|
1352
|
+
rb_define_method(cTimestampTokenInfo, "initialize", ossl_ts_token_info_initialize, 1);
|
1353
|
+
rb_define_method(cTimestampTokenInfo, "version", ossl_ts_token_info_get_version, 0);
|
1354
|
+
rb_define_method(cTimestampTokenInfo, "policy_id", ossl_ts_token_info_get_policy_id, 0);
|
1355
|
+
rb_define_method(cTimestampTokenInfo, "algorithm", ossl_ts_token_info_get_algorithm, 0);
|
1356
|
+
rb_define_method(cTimestampTokenInfo, "message_imprint", ossl_ts_token_info_get_msg_imprint, 0);
|
1357
|
+
rb_define_method(cTimestampTokenInfo, "serial_number", ossl_ts_token_info_get_serial_number, 0);
|
1358
|
+
rb_define_method(cTimestampTokenInfo, "gen_time", ossl_ts_token_info_get_gen_time, 0);
|
1359
|
+
rb_define_method(cTimestampTokenInfo, "ordering", ossl_ts_token_info_get_ordering, 0);
|
1360
|
+
rb_define_method(cTimestampTokenInfo, "nonce", ossl_ts_token_info_get_nonce, 0);
|
1361
|
+
rb_define_method(cTimestampTokenInfo, "to_der", ossl_ts_token_info_to_der, 0);
|
1362
|
+
|
1363
|
+
/* Document-class: OpenSSL::Timestamp::Request
|
1364
|
+
* Allows to create timestamp requests or parse existing ones. A Request is
|
1365
|
+
* also needed for creating timestamps from scratch with Factory. When
|
1366
|
+
* created from scratch, some default values are set:
|
1367
|
+
* * version is set to +1+
|
1368
|
+
* * cert_requested is set to +true+
|
1369
|
+
* * algorithm, message_imprint, policy_id, and nonce are set to +false+
|
1370
|
+
*/
|
1371
|
+
cTimestampRequest = rb_define_class_under(mTimestamp, "Request", rb_cObject);
|
1372
|
+
rb_define_alloc_func(cTimestampRequest, ossl_ts_req_alloc);
|
1373
|
+
rb_define_method(cTimestampRequest, "initialize", ossl_ts_req_initialize, -1);
|
1374
|
+
rb_define_method(cTimestampRequest, "version=", ossl_ts_req_set_version, 1);
|
1375
|
+
rb_define_method(cTimestampRequest, "version", ossl_ts_req_get_version, 0);
|
1376
|
+
rb_define_method(cTimestampRequest, "algorithm=", ossl_ts_req_set_algorithm, 1);
|
1377
|
+
rb_define_method(cTimestampRequest, "algorithm", ossl_ts_req_get_algorithm, 0);
|
1378
|
+
rb_define_method(cTimestampRequest, "message_imprint=", ossl_ts_req_set_msg_imprint, 1);
|
1379
|
+
rb_define_method(cTimestampRequest, "message_imprint", ossl_ts_req_get_msg_imprint, 0);
|
1380
|
+
rb_define_method(cTimestampRequest, "policy_id=", ossl_ts_req_set_policy_id, 1);
|
1381
|
+
rb_define_method(cTimestampRequest, "policy_id", ossl_ts_req_get_policy_id, 0);
|
1382
|
+
rb_define_method(cTimestampRequest, "nonce=", ossl_ts_req_set_nonce, 1);
|
1383
|
+
rb_define_method(cTimestampRequest, "nonce", ossl_ts_req_get_nonce, 0);
|
1384
|
+
rb_define_method(cTimestampRequest, "cert_requested=", ossl_ts_req_set_cert_requested, 1);
|
1385
|
+
rb_define_method(cTimestampRequest, "cert_requested?", ossl_ts_req_get_cert_requested, 0);
|
1386
|
+
rb_define_method(cTimestampRequest, "to_der", ossl_ts_req_to_der, 0);
|
1387
|
+
|
1388
|
+
/*
|
1389
|
+
* Indicates a successful response. Equal to +0+.
|
1390
|
+
*/
|
1391
|
+
rb_define_const(cTimestampResponse, "GRANTED", INT2NUM(TS_STATUS_GRANTED));
|
1392
|
+
/*
|
1393
|
+
* Indicates a successful response that probably contains modifications
|
1394
|
+
* from the initial request. Equal to +1+.
|
1395
|
+
*/
|
1396
|
+
rb_define_const(cTimestampResponse, "GRANTED_WITH_MODS", INT2NUM(TS_STATUS_GRANTED_WITH_MODS));
|
1397
|
+
/*
|
1398
|
+
* Indicates a failure. No timestamp token was created. Equal to +2+.
|
1399
|
+
*/
|
1400
|
+
rb_define_const(cTimestampResponse, "REJECTION", INT2NUM(TS_STATUS_REJECTION));
|
1401
|
+
/*
|
1402
|
+
* Indicates a failure. No timestamp token was created. Equal to +3+.
|
1403
|
+
*/
|
1404
|
+
rb_define_const(cTimestampResponse, "WAITING", INT2NUM(TS_STATUS_WAITING));
|
1405
|
+
/*
|
1406
|
+
* Indicates a failure. No timestamp token was created. Revocation of a
|
1407
|
+
* certificate is imminent. Equal to +4+.
|
1408
|
+
*/
|
1409
|
+
rb_define_const(cTimestampResponse, "REVOCATION_WARNING", INT2NUM(TS_STATUS_REVOCATION_WARNING));
|
1410
|
+
/*
|
1411
|
+
* Indicates a failure. No timestamp token was created. A certificate
|
1412
|
+
* has been revoked. Equal to +5+.
|
1413
|
+
*/
|
1414
|
+
rb_define_const(cTimestampResponse, "REVOCATION_NOTIFICATION", INT2NUM(TS_STATUS_REVOCATION_NOTIFICATION));
|
1415
|
+
|
1416
|
+
/* Document-class: OpenSSL::Timestamp::Factory
|
1417
|
+
*
|
1418
|
+
* Used to generate a Response from scratch.
|
1419
|
+
*
|
1420
|
+
* Please bear in mind that the implementation will always apply and prefer
|
1421
|
+
* the policy object identifier given in the request over the default policy
|
1422
|
+
* id specified in the Factory. As a consequence, +default_policy_id+ will
|
1423
|
+
* only be applied if no Request#policy_id was given. But this also means
|
1424
|
+
* that one needs to check the policy identifier in the request manually
|
1425
|
+
* before creating the Response, e.g. to check whether it complies to a
|
1426
|
+
* specific set of acceptable policies.
|
1427
|
+
*
|
1428
|
+
* There exists also the possibility to add certificates (instances of
|
1429
|
+
* OpenSSL::X509::Certificate) besides the timestamping certificate
|
1430
|
+
* that will be included in the resulting timestamp token if
|
1431
|
+
* Request#cert_requested? is +true+. Ideally, one would also include any
|
1432
|
+
* intermediate certificates (the root certificate can be left out - in
|
1433
|
+
* order to trust it any verifying party will have to be in its possession
|
1434
|
+
* anyway). This simplifies validation of the timestamp since these
|
1435
|
+
* intermediate certificates are "already there" and need not be passed as
|
1436
|
+
* external parameters to Response#verify anymore, thus minimizing external
|
1437
|
+
* resources needed for verification.
|
1438
|
+
*
|
1439
|
+
* ===Example: Inclusion of (untrusted) intermediate certificates
|
1440
|
+
*
|
1441
|
+
* Assume we received a timestamp request that has set Request#policy_id to
|
1442
|
+
* +nil+ and Request#cert_requested? to true. The raw request bytes are
|
1443
|
+
* stored in a variable called +req_raw+. We'd still like to integrate
|
1444
|
+
* the necessary intermediate certificates (in +inter1.cer+ and
|
1445
|
+
* +inter2.cer+) to simplify validation of the resulting Response. +ts.p12+
|
1446
|
+
* is a PKCS#12-compatible file including the private key and the
|
1447
|
+
* timestamping certificate.
|
1448
|
+
*
|
1449
|
+
* req = OpenSSL::Timestamp::Request.new(raw_bytes)
|
1450
|
+
* p12 = OpenSSL::PKCS12.new(File.open('ts.p12', 'rb'), 'pwd')
|
1451
|
+
* inter1 = OpenSSL::X509::Certificate.new(File.open('inter1.cer', 'rb')
|
1452
|
+
* inter2 = OpenSSL::X509::Certificate.new(File.open('inter2.cer', 'rb')
|
1453
|
+
* fac = OpenSSL::Timestamp::Factory.new
|
1454
|
+
* fac.gen_time = Time.now
|
1455
|
+
* fac.serial_number = 1
|
1456
|
+
* fac.allowed_digests = ["sha256", "sha384", "sha512"]
|
1457
|
+
* #needed because the Request contained no policy identifier
|
1458
|
+
* fac.default_policy_id = '1.2.3.4.5'
|
1459
|
+
* fac.additional_certificates = [ inter1, inter2 ]
|
1460
|
+
* timestamp = fac.create_timestamp(p12.key, p12.certificate, req)
|
1461
|
+
*
|
1462
|
+
* ==Attributes
|
1463
|
+
*
|
1464
|
+
* ===default_policy_id
|
1465
|
+
*
|
1466
|
+
* Request#policy_id will always be preferred over this if present in the
|
1467
|
+
* Request, only if Request#policy_id is nil default_policy will be used.
|
1468
|
+
* If none of both is present, a TimestampError will be raised when trying
|
1469
|
+
* to create a Response.
|
1470
|
+
*
|
1471
|
+
* call-seq:
|
1472
|
+
* factory.default_policy_id = "string" -> string
|
1473
|
+
* factory.default_policy_id -> string or nil
|
1474
|
+
*
|
1475
|
+
* ===serial_number
|
1476
|
+
*
|
1477
|
+
* Sets or retrieves the serial number to be used for timestamp creation.
|
1478
|
+
* Must be present for timestamp creation.
|
1479
|
+
*
|
1480
|
+
* call-seq:
|
1481
|
+
* factory.serial_number = number -> number
|
1482
|
+
* factory.serial_number -> number or nil
|
1483
|
+
*
|
1484
|
+
* ===gen_time
|
1485
|
+
*
|
1486
|
+
* Sets or retrieves the Time value to be used in the Response. Must be
|
1487
|
+
* present for timestamp creation.
|
1488
|
+
*
|
1489
|
+
* call-seq:
|
1490
|
+
* factory.gen_time = Time -> Time
|
1491
|
+
* factory.gen_time -> Time or nil
|
1492
|
+
*
|
1493
|
+
* ===additional_certs
|
1494
|
+
*
|
1495
|
+
* Sets or retrieves additional certificates apart from the timestamp
|
1496
|
+
* certificate (e.g. intermediate certificates) to be added to the Response.
|
1497
|
+
* Must be an Array of OpenSSL::X509::Certificate.
|
1498
|
+
*
|
1499
|
+
* call-seq:
|
1500
|
+
* factory.additional_certs = [cert1, cert2] -> [ cert1, cert2 ]
|
1501
|
+
* factory.additional_certs -> array or nil
|
1502
|
+
*
|
1503
|
+
* ===allowed_digests
|
1504
|
+
*
|
1505
|
+
* Sets or retrieves the digest algorithms that the factory is allowed
|
1506
|
+
* create timestamps for. Known vulnerable or weak algorithms should not be
|
1507
|
+
* allowed where possible.
|
1508
|
+
* Must be an Array of String or OpenSSL::Digest subclass instances.
|
1509
|
+
*
|
1510
|
+
* call-seq:
|
1511
|
+
* factory.allowed_digests = ["sha1", OpenSSL::Digest.new('SHA256').new] -> [ "sha1", OpenSSL::Digest) ]
|
1512
|
+
* factory.allowed_digests -> array or nil
|
1513
|
+
*
|
1514
|
+
*/
|
1515
|
+
cTimestampFactory = rb_define_class_under(mTimestamp, "Factory", rb_cObject);
|
1516
|
+
rb_attr(cTimestampFactory, rb_intern_const("allowed_digests"), 1, 1, 0);
|
1517
|
+
rb_attr(cTimestampFactory, rb_intern_const("default_policy_id"), 1, 1, 0);
|
1518
|
+
rb_attr(cTimestampFactory, rb_intern_const("serial_number"), 1, 1, 0);
|
1519
|
+
rb_attr(cTimestampFactory, rb_intern_const("gen_time"), 1, 1, 0);
|
1520
|
+
rb_attr(cTimestampFactory, rb_intern_const("additional_certs"), 1, 1, 0);
|
1521
|
+
rb_define_method(cTimestampFactory, "create_timestamp", ossl_tsfac_create_ts, 3);
|
1522
|
+
}
|
1523
|
+
|
1524
|
+
#endif
|