openssl 2.1.1 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +9 -7
  3. data/History.md +165 -0
  4. data/README.md +2 -2
  5. data/ext/openssl/extconf.rb +51 -27
  6. data/ext/openssl/openssl_missing.h +39 -4
  7. data/ext/openssl/ossl.c +61 -27
  8. data/ext/openssl/ossl.h +8 -5
  9. data/ext/openssl/ossl_asn1.c +27 -1
  10. data/ext/openssl/ossl_bn.c +92 -24
  11. data/ext/openssl/ossl_bn.h +2 -1
  12. data/ext/openssl/ossl_cipher.c +33 -24
  13. data/ext/openssl/ossl_digest.c +22 -53
  14. data/ext/openssl/ossl_engine.c +2 -12
  15. data/ext/openssl/ossl_hmac.c +5 -11
  16. data/ext/openssl/ossl_kdf.c +3 -19
  17. data/ext/openssl/ossl_ns_spki.c +1 -1
  18. data/ext/openssl/ossl_ocsp.c +6 -11
  19. data/ext/openssl/ossl_ocsp.h +3 -3
  20. data/ext/openssl/ossl_pkcs12.c +1 -0
  21. data/ext/openssl/ossl_pkcs7.c +4 -19
  22. data/ext/openssl/ossl_pkcs7.h +16 -0
  23. data/ext/openssl/ossl_pkey.c +206 -17
  24. data/ext/openssl/ossl_pkey.h +6 -6
  25. data/ext/openssl/ossl_pkey_dh.c +1 -1
  26. data/ext/openssl/ossl_pkey_dsa.c +2 -2
  27. data/ext/openssl/ossl_pkey_ec.c +38 -8
  28. data/ext/openssl/ossl_pkey_rsa.c +17 -9
  29. data/ext/openssl/ossl_rand.c +2 -40
  30. data/ext/openssl/ossl_ssl.c +205 -75
  31. data/ext/openssl/ossl_ts.c +1524 -0
  32. data/ext/openssl/ossl_ts.h +16 -0
  33. data/ext/openssl/ossl_x509.c +91 -0
  34. data/ext/openssl/ossl_x509cert.c +2 -2
  35. data/ext/openssl/ossl_x509ext.c +15 -0
  36. data/ext/openssl/ossl_x509name.c +15 -10
  37. data/ext/openssl/ossl_x509store.c +40 -22
  38. data/lib/openssl/bn.rb +1 -1
  39. data/lib/openssl/buffering.rb +33 -17
  40. data/lib/openssl/cipher.rb +1 -1
  41. data/lib/openssl/config.rb +53 -26
  42. data/lib/openssl/digest.rb +10 -12
  43. data/lib/openssl/hmac.rb +13 -0
  44. data/lib/openssl/marshal.rb +30 -0
  45. data/lib/openssl/pkcs5.rb +1 -1
  46. data/lib/openssl/pkey.rb +18 -1
  47. data/lib/openssl/ssl.rb +46 -7
  48. data/lib/openssl/version.rb +5 -0
  49. data/lib/openssl/x509.rb +155 -1
  50. data/lib/openssl.rb +25 -9
  51. metadata +25 -9
  52. data/ext/openssl/deprecation.rb +0 -23
  53. 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