openssl 2.1.4 → 2.2.0

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