openssl-custom 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/BSDL +22 -0
  3. data/CONTRIBUTING.md +132 -0
  4. data/History.md +485 -0
  5. data/LICENSE.txt +56 -0
  6. data/README.md +66 -0
  7. data/ext/openssl/extconf.rb +190 -0
  8. data/ext/openssl/openssl_missing.c +106 -0
  9. data/ext/openssl/openssl_missing.h +257 -0
  10. data/ext/openssl/ossl.c +1282 -0
  11. data/ext/openssl/ossl.h +181 -0
  12. data/ext/openssl/ossl_asn1.c +1878 -0
  13. data/ext/openssl/ossl_asn1.h +62 -0
  14. data/ext/openssl/ossl_bio.c +42 -0
  15. data/ext/openssl/ossl_bio.h +16 -0
  16. data/ext/openssl/ossl_bn.c +1270 -0
  17. data/ext/openssl/ossl_bn.h +26 -0
  18. data/ext/openssl/ossl_cipher.c +1075 -0
  19. data/ext/openssl/ossl_cipher.h +20 -0
  20. data/ext/openssl/ossl_config.c +89 -0
  21. data/ext/openssl/ossl_config.h +19 -0
  22. data/ext/openssl/ossl_digest.c +425 -0
  23. data/ext/openssl/ossl_digest.h +20 -0
  24. data/ext/openssl/ossl_engine.c +567 -0
  25. data/ext/openssl/ossl_engine.h +19 -0
  26. data/ext/openssl/ossl_hmac.c +389 -0
  27. data/ext/openssl/ossl_hmac.h +18 -0
  28. data/ext/openssl/ossl_kdf.c +303 -0
  29. data/ext/openssl/ossl_kdf.h +6 -0
  30. data/ext/openssl/ossl_ns_spki.c +405 -0
  31. data/ext/openssl/ossl_ns_spki.h +19 -0
  32. data/ext/openssl/ossl_ocsp.c +2013 -0
  33. data/ext/openssl/ossl_ocsp.h +23 -0
  34. data/ext/openssl/ossl_pkcs12.c +257 -0
  35. data/ext/openssl/ossl_pkcs12.h +13 -0
  36. data/ext/openssl/ossl_pkcs7.c +1098 -0
  37. data/ext/openssl/ossl_pkcs7.h +36 -0
  38. data/ext/openssl/ossl_pkey.c +673 -0
  39. data/ext/openssl/ossl_pkey.h +241 -0
  40. data/ext/openssl/ossl_pkey_dh.c +650 -0
  41. data/ext/openssl/ossl_pkey_dsa.c +664 -0
  42. data/ext/openssl/ossl_pkey_ec.c +1827 -0
  43. data/ext/openssl/ossl_pkey_rsa.c +966 -0
  44. data/ext/openssl/ossl_rand.c +200 -0
  45. data/ext/openssl/ossl_rand.h +18 -0
  46. data/ext/openssl/ossl_ssl.c +3080 -0
  47. data/ext/openssl/ossl_ssl.h +36 -0
  48. data/ext/openssl/ossl_ssl_session.c +332 -0
  49. data/ext/openssl/ossl_ts.c +1524 -0
  50. data/ext/openssl/ossl_ts.h +16 -0
  51. data/ext/openssl/ossl_x509.c +262 -0
  52. data/ext/openssl/ossl_x509.h +115 -0
  53. data/ext/openssl/ossl_x509attr.c +324 -0
  54. data/ext/openssl/ossl_x509cert.c +846 -0
  55. data/ext/openssl/ossl_x509crl.c +542 -0
  56. data/ext/openssl/ossl_x509ext.c +491 -0
  57. data/ext/openssl/ossl_x509name.c +590 -0
  58. data/ext/openssl/ossl_x509req.c +441 -0
  59. data/ext/openssl/ossl_x509revoked.c +300 -0
  60. data/ext/openssl/ossl_x509store.c +902 -0
  61. data/ext/openssl/ruby_missing.h +24 -0
  62. data/lib/openssl/bn.rb +40 -0
  63. data/lib/openssl/buffering.rb +478 -0
  64. data/lib/openssl/cipher.rb +67 -0
  65. data/lib/openssl/config.rb +501 -0
  66. data/lib/openssl/digest.rb +73 -0
  67. data/lib/openssl/hmac.rb +13 -0
  68. data/lib/openssl/marshal.rb +30 -0
  69. data/lib/openssl/pkcs5.rb +22 -0
  70. data/lib/openssl/pkey.rb +42 -0
  71. data/lib/openssl/ssl.rb +542 -0
  72. data/lib/openssl/version.rb +5 -0
  73. data/lib/openssl/x509.rb +369 -0
  74. data/lib/openssl.rb +38 -0
  75. metadata +196 -0
@@ -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