Ruby: ext/openssl/ossl_ts.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

ossl_ts.c
Go to the documentation of this file.
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
65static VALUE mTimestamp;
66static VALUE eTimestampError;
67static VALUE cTimestampRequest;
68static VALUE cTimestampResponse;
69static VALUE cTimestampTokenInfo;
70static VALUE cTimestampFactory;
71static VALUE sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE;
72static VALUE sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE;
73static VALUE sSYSTEM_FAILURE;
74
75static void
76ossl_ts_req_free(void *ptr)
77{
78 TS_REQ_free(ptr);
79}
80
81static 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
89static void
90ossl_ts_resp_free(void *ptr)
91{
92 TS_RESP_free(ptr);
93}
94
95static 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
103static void
104ossl_ts_token_info_free(void *ptr)
105{
106 TS_TST_INFO_free(ptr);
107}
108
109static 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
117static VALUE
118asn1_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
135static ASN1_OBJECT*
136obj_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
148static VALUE
149get_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
166static VALUE
167ossl_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 */
193static VALUE
194ossl_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 */
224static VALUE
225ossl_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 */
247static VALUE
248ossl_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 */
273static VALUE
274ossl_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 */
296static VALUE
297ossl_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 */
317static VALUE
318ossl_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 */
333static VALUE
334ossl_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 */
355static VALUE
356ossl_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 */
378static VALUE
379ossl_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 */
402static VALUE
403ossl_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 */
422static VALUE
423ossl_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 */
445static VALUE
446ossl_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 */
461static VALUE
462ossl_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 */
478static VALUE
479ossl_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
500static VALUE
501ossl_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 */
524static VALUE
525ossl_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 */
551static VALUE
552ossl_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 */
590static VALUE
591ossl_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 */
636static VALUE
637ossl_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 */
665static VALUE
666ossl_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 */
692static VALUE
693ossl_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 */
721static VALUE
722ossl_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 */
745static VALUE
746ossl_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 */
774static VALUE
775ossl_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
844static VALUE
845ossl_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 */
868static VALUE
869ossl_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 */
895static VALUE
896ossl_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 */
916static VALUE
917ossl_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 */
938static VALUE
939ossl_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 */
963static VALUE
964ossl_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 */
987static VALUE
988ossl_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 */
1003static VALUE
1004ossl_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 */
1029static VALUE
1030ossl_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 */
1045static VALUE
1046ossl_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 */
1064static VALUE
1065ossl_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
1073static ASN1_INTEGER *
1074ossl_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
1082static int
1083#if !defined(LIBRESSL_VERSION_NUMBER)
1084ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec)
1085#else
1086ossl_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 */
1118static VALUE
1119ossl_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
1234end:
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 */
1248void
1249Init_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
rb_cArray
VALUE rb_cArray
Definition: array.c:40
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1301
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:749
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1672
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:653
ptr
struct RIMemo * ptr
Definition: debug.c:88
num
big_t * num
Definition: enough.c:232
out
string_t out
Definition: enough.c:230
len
uint8_t len
Definition: escape.c:17
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
RSTRING_PTR
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
rb_cTime
VALUE rb_cTime
Definition: time.c:645
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:797
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:871
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:895
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2296
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1105
rb_jump_tag
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:921
rb_cObject
VALUE rb_cObject
Object class.
Definition: object.c:49
rb_obj_is_instance_of
VALUE rb_obj_is_instance_of(VALUE, VALUE)
Determines if obj is an instance of c.
Definition: object.c:707
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:724
in
unsigned in(void *in_desc, z_const unsigned char **buf)
Definition: gun.c:89
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:1077
rb_str_new2
#define rb_str_new2
Definition: string.h:276
rb_str_new
#define rb_str_new(str, len)
Definition: string.h:213
rb_str_set_len
void rb_str_set_len(VALUE, long)
Definition: string.c:2842
rb_attr
void rb_attr(VALUE, ID, int, int, int)
Definition: vm_method.c:1508
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
ID2SYM
#define ID2SYM
Definition: symbol.h:44
rb_intern
ID rb_intern(const char *)
Definition: symbol.c:785
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:3150
INT2NUM
#define INT2NUM
Definition: int.h:43
LONG2NUM
#define LONG2NUM
Definition: long.h:50
NUM2LONG
#define NUM2LONG
Definition: long.h:51
nid
int nid
Definition: openssl_missing.c:28
TS_RESP_CTX_set_time_cb
#define TS_RESP_CTX_set_time_cb(ctx, callback, dta)
TS_VERIFY_CTX_set_store
#define TS_VERIFY_CTX_set_store(ctx, str)
X509_up_ref
#define X509_up_ref(x)
Definition: openssl_missing.h:126
TS_VERIFY_CTS_set_certs
#define TS_VERIFY_CTS_set_certs(ctx, crts)
key
key
Definition: openssl_missing.h:185
TS_STATUS_INFO_get0_failure_info
#define TS_STATUS_INFO_get0_failure_info(a)
TS_STATUS_INFO_get0_text
#define TS_STATUS_INFO_get0_text(a)
TS_VERIFY_CTX_add_flags
#define TS_VERIFY_CTX_add_flags(ctx, f)
TS_STATUS_INFO_get0_status
#define TS_STATUS_INFO_get0_status(a)
mOSSL
VALUE mOSSL
Definition: ossl.c:231
ossl_to_der
VALUE ossl_to_der(VALUE obj)
Definition: ossl.c:244
ossl_to_der_if_possible
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:255
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
eOSSLError
VALUE eOSSLError
Definition: ossl.c:236
ossl_clear_error
void ossl_clear_error(void)
Definition: ossl.c:304
ossl.h
STACK_OF
STACK_OF(X509) *ossl_x509_ary2sk(VALUE)
asn1integer_to_num
VALUE asn1integer_to_num(const ASN1_INTEGER *ai)
Definition: ossl_asn1.c:101
asn1time_to_time
VALUE asn1time_to_time(const ASN1_TIME *time)
Definition: ossl_asn1.c:20
num_to_asn1integer
ASN1_INTEGER * num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
Definition: ossl_asn1.c:124
eASN1Error
VALUE eASN1Error
Definition: ossl_asn1.c:156
asn1str_to_str
VALUE asn1str_to_str(const ASN1_STRING *str)
Definition: ossl_asn1.c:92
ossl_obj2bio
BIO * ossl_obj2bio(volatile VALUE *pobj)
Definition: ossl_bio.c:13
ossl_membio2str
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
ossl_evp_get_digestbyname
const EVP_MD * ossl_evp_get_digestbyname(VALUE obj)
Definition: ossl_digest.c:45
cPKCS7
VALUE cPKCS7
Definition: ossl_pkcs7.c:52
SetPKCS7
#define SetPKCS7(obj, pkcs7)
Definition: ossl_pkcs7.h:15
NewPKCS7
#define NewPKCS7(klass)
Definition: ossl_pkcs7.h:13
GetPrivPKeyPtr
EVP_PKEY * GetPrivPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:245
SetTSTokenInfo
#define SetTSTokenInfo(obj, info)
Definition: ossl_ts.c:46
SetTSRequest
#define SetTSRequest(obj, req)
Definition: ossl_ts.c:16
NewTSTokenInfo
#define NewTSTokenInfo(klass)
Definition: ossl_ts.c:44
GetTSRequest
#define GetTSRequest(obj, req)
Definition: ossl_ts.c:22
ossl_tsfac_get_additional_certs
#define ossl_tsfac_get_additional_certs(o)
Definition: ossl_ts.c:62
GetTSTokenInfo
#define GetTSTokenInfo(obj, info)
Definition: ossl_ts.c:52
ossl_tsfac_get_serial_number
#define ossl_tsfac_get_serial_number(o)
Definition: ossl_ts.c:60
ossl_tsfac_get_gen_time
#define ossl_tsfac_get_gen_time(o)
Definition: ossl_ts.c:61
NewTSResponse
#define NewTSResponse(klass)
Definition: ossl_ts.c:29
ossl_tsfac_get_default_policy_id
#define ossl_tsfac_get_default_policy_id(o)
Definition: ossl_ts.c:59
NewTSRequest
#define NewTSRequest(klass)
Definition: ossl_ts.c:14
ossl_tsfac_get_allowed_digests
#define ossl_tsfac_get_allowed_digests(o)
Definition: ossl_ts.c:63
SetTSResponse
#define SetTSResponse(obj, resp)
Definition: ossl_ts.c:31
Init_ossl_ts
void Init_ossl_ts(void)
Definition: ossl_ts.c:1249
GetTSResponse
#define GetTSResponse(obj, resp)
Definition: ossl_ts.c:37
ossl_x509_new
VALUE ossl_x509_new(X509 *)
Definition: ossl_x509cert.c:51
GetX509StorePtr
X509_STORE * GetX509StorePtr(VALUE)
Definition: ossl_x509store.c:133
GetX509CertPtr
X509 * GetX509CertPtr(VALUE)
Definition: ossl_x509cert.c:71
eX509AttrError
VALUE eX509AttrError
Definition: ossl_x509attr.c:31
RARRAY_LEN
#define RARRAY_LEN
Definition: rarray.h:52
DATA_PTR
#define DATA_PTR(obj)
Definition: rdata.h:56
NULL
#define NULL
Definition: regenc.h:69
StringValue
#define StringValue(v)
Definition: rstring.h:50
RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
argc
int argc
Definition: ruby.c:240
argv
char ** argv
Definition: ruby.c:241
Qtrue
#define Qtrue
Definition: special_consts.h:52
RTEST
#define RTEST
Definition: special_consts.h:42
Qnil
#define Qnil
Definition: special_consts.h:51
Qfalse
#define Qfalse
Definition: special_consts.h:50
NIL_P
#define NIL_P
Definition: special_consts.h:46
rb_data_type_struct
Definition: rtypeddata.h:70
VALUE
unsigned long VALUE
Definition: value.h:38