openssl 2.1.2 → 3.0.0

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