Object
Immutable and read-only representation of a timestamp response returned from a timestamp server after receiving an associated Request
. Allows access to specific information about the response but also allows to verify the Response
.
Indicates a successful response. Equal to 0
.
Indicates a successful response that probably contains modifications from the initial request. Equal to 1
.
Indicates a failure. No timestamp token was created. Equal to 2
.
Indicates a failure. No timestamp token was created. A certificate has been revoked. Equal to 5
.
Indicates a failure. No timestamp token was created. Revocation of a certificate is imminent. Equal to 4
.
Indicates a failure. No timestamp token was created. Equal to 3
.
Creates a Response
from a File
or string
parameter, the corresponding File
or string
must be DER-encoded. Please note that Response
is an immutable read-only class. If you'd like to create timestamps please refer to Factory
instead.
static VALUE ossl_ts_resp_initialize(VALUE self, VALUE der) { TS_RESP *ts_resp = DATA_PTR(self); BIO *in; der = ossl_to_der_if_possible(der); in = ossl_obj2bio(&der); ts_resp = d2i_TS_RESP_bio(in, &ts_resp); BIO_free(in); if (!ts_resp) { DATA_PTR(self) = NULL; ossl_raise(eTimestampError, "Error when decoding the timestamp response"); } DATA_PTR(self) = ts_resp; return self; }
In cases no timestamp token has been created, this field contains further info about the reason why response creation failed. The method returns either nil (the request was successful and a timestamp token was created) or one of the following:
:BAD_ALG - Indicates that the timestamp server rejects the message imprint algorithm used in the Request
:BAD_REQUEST - Indicates that the timestamp server was not able to process the Request
properly
:BAD_DATA_FORMAT - Indicates that the timestamp server was not able to parse certain data in the Request
:TIME_NOT_AVAILABLE - Indicates that the server could not access its time source
:UNACCEPTED_POLICY - Indicates that the requested policy identifier is not recognized or supported by the timestamp server
:UNACCEPTED_EXTENSIION - Indicates that an extension in the Request
is not supported by the timestamp server
:ADD_INFO_NOT_AVAILABLE -Indicates that additional information requested is either not understood or currently not available
:SYSTEM_FAILURE - Timestamp
creation failed due to an internal error that occurred on the timestamp server
static VALUE ossl_ts_resp_get_failure_info(VALUE self) { TS_RESP *resp; TS_STATUS_INFO *si; /* The ASN1_BIT_STRING_get_bit changed from 1.0.0. to 1.1.0, making this * const. */ #if defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO) const ASN1_BIT_STRING *fi; #else ASN1_BIT_STRING *fi; #endif GetTSResponse(self, resp); si = TS_RESP_get_status_info(resp); fi = TS_STATUS_INFO_get0_failure_info(si); if (!fi) return Qnil; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_ALG)) return sBAD_ALG; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_REQUEST)) return sBAD_REQUEST; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_DATA_FORMAT)) return sBAD_DATA_FORMAT; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_TIME_NOT_AVAILABLE)) return sTIME_NOT_AVAILABLE; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_POLICY)) return sUNACCEPTED_POLICY; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_EXTENSION)) return sUNACCEPTED_EXTENSION; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_ADD_INFO_NOT_AVAILABLE)) return sADD_INFO_NOT_AVAILABLE; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_SYSTEM_FAILURE)) return sSYSTEM_FAILURE; ossl_raise(eTimestampError, "Unrecognized failure info."); }
Returns one of GRANTED
, GRANTED_WITH_MODS
, REJECTION
, WAITING
, REVOCATION_WARNING
or REVOCATION_NOTIFICATION
. A timestamp token has been created only in case status
is equal to GRANTED
or GRANTED_WITH_MODS
.
static VALUE ossl_ts_resp_get_status(VALUE self) { TS_RESP *resp; TS_STATUS_INFO *si; const ASN1_INTEGER *st; GetTSResponse(self, resp); si = TS_RESP_get_status_info(resp); st = TS_STATUS_INFO_get0_status(si); return asn1integer_to_num(st); }
In cases of failure this field may contain an array of strings further describing the origin of the failure.
static VALUE ossl_ts_resp_get_status_text(VALUE self) { TS_RESP *resp; TS_STATUS_INFO *si; const STACK_OF(ASN1_UTF8STRING) *text; ASN1_UTF8STRING *current; int i; VALUE ret = rb_ary_new(); GetTSResponse(self, resp); si = TS_RESP_get_status_info(resp); if ((text = TS_STATUS_INFO_get0_text(si))) { for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) { current = sk_ASN1_UTF8STRING_value(text, i); rb_ary_push(ret, asn1str_to_str(current)); } } return ret; }
Returns the Response
in DER-encoded form.
static VALUE ossl_ts_resp_to_der(VALUE self) { TS_RESP *resp; GetTSResponse(self, resp); return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP); }
If a timestamp token is present, this returns it in the form of a OpenSSL::PKCS7
.
static VALUE ossl_ts_resp_get_token(VALUE self) { TS_RESP *resp; PKCS7 *p7, *copy; VALUE obj; GetTSResponse(self, resp); if (!(p7 = TS_RESP_get_token(resp))) return Qnil; obj = NewPKCS7(cPKCS7); if (!(copy = PKCS7_dup(p7))) ossl_raise(eTimestampError, NULL); SetPKCS7(obj, copy); return obj; }
Get the response's token info if present.
static VALUE ossl_ts_resp_get_token_info(VALUE self) { TS_RESP *resp; TS_TST_INFO *info, *copy; VALUE obj; GetTSResponse(self, resp); if (!(info = TS_RESP_get_tst_info(resp))) return Qnil; obj = NewTSTokenInfo(cTimestampTokenInfo); if (!(copy = TS_TST_INFO_dup(info))) ossl_raise(eTimestampError, NULL); SetTSTokenInfo(obj, copy); return obj; }
If the Request
specified to request the TSA certificate (Request#cert_requested = true), then this field contains the certificate of the timestamp authority.
static VALUE ossl_ts_resp_get_tsa_certificate(VALUE self) { TS_RESP *resp; PKCS7 *p7; PKCS7_SIGNER_INFO *ts_info; X509 *cert; GetTSResponse(self, resp); if (!(p7 = TS_RESP_get_token(resp))) return Qnil; ts_info = sk_PKCS7_SIGNER_INFO_value(p7->d.sign->signer_info, 0); cert = PKCS7_cert_from_signer_info(p7, ts_info); if (!cert) return Qnil; return ossl_x509_new(cert); }
Verifies a timestamp token by checking the signature, validating the certificate chain implied by tsa_certificate
and by checking conformance to a given Request
. Mandatory parameters are the Request
associated to this Response
, and an OpenSSL::X509::Store
of trusted roots.
Intermediate certificates can optionally be supplied for creating the certificate chain. These intermediate certificates must all be instances of OpenSSL::X509::Certificate
.
If validation fails, several kinds of exceptions can be raised:
TypeError if types don't fit
TimestampError
if something is wrong with the timestamp token itself, if it is not conformant to the Request
, or if validation of the timestamp certificate chain fails.
static VALUE ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self) { VALUE ts_req, store, intermediates; TS_RESP *resp; TS_REQ *req; X509_STORE *x509st; TS_VERIFY_CTX *ctx; STACK_OF(X509) *x509inter = NULL; PKCS7* p7; X509 *cert; int status, i, ok; rb_scan_args(argc, argv, "21", &ts_req, &store, &intermediates); GetTSResponse(self, resp); GetTSRequest(ts_req, req); x509st = GetX509StorePtr(store); if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(req, NULL))) { ossl_raise(eTimestampError, "Error when creating the verification context."); } if (!NIL_P(intermediates)) { x509inter = ossl_protect_x509_ary2sk(intermediates, &status); if (status) { TS_VERIFY_CTX_free(ctx); rb_jump_tag(status); } } else if (!(x509inter = sk_X509_new_null())) { TS_VERIFY_CTX_free(ctx); ossl_raise(eTimestampError, "sk_X509_new_null"); } if (!(p7 = TS_RESP_get_token(resp))) { TS_VERIFY_CTX_free(ctx); sk_X509_pop_free(x509inter, X509_free); ossl_raise(eTimestampError, "TS_RESP_get_token"); } for (i=0; i < sk_X509_num(p7->d.sign->cert); i++) { cert = sk_X509_value(p7->d.sign->cert, i); if (!sk_X509_push(x509inter, cert)) { sk_X509_pop_free(x509inter, X509_free); TS_VERIFY_CTX_free(ctx); ossl_raise(eTimestampError, "sk_X509_push"); } X509_up_ref(cert); } TS_VERIFY_CTX_set_certs(ctx, x509inter); TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE); TS_VERIFY_CTX_set_store(ctx, x509st); ok = TS_RESP_verify_response(ctx, resp); /* * TS_VERIFY_CTX_set_store() call above does not increment the reference * counter, so it must be unset before TS_VERIFY_CTX_free() is called. */ TS_VERIFY_CTX_set_store(ctx, NULL); TS_VERIFY_CTX_free(ctx); if (!ok) ossl_raise(eTimestampError, "TS_RESP_verify_response"); return self; }