diff options
author | Ben Toews <mastahyeti@gmail.com> | 2018-08-09 09:48:44 -0600 |
---|---|---|
committer | Ben Toews <mastahyeti@gmail.com> | 2018-08-09 09:48:44 -0600 |
commit | 703e821b0159f056f9eb369a079709f97c18251e (patch) | |
tree | d599fda87db6b1460dd4b1433334ad7797c11ecf /ext/openssl/ossl_ts.c | |
parent | e759f07e01467bef913f3dd678b030649f1041fc (diff) | |
download | ruby-openssl-703e821b0159f056f9eb369a079709f97c18251e.tar.gz |
ts: move TS_TST_INFO accessors to a new Timestamp::TokenInfo class
Diffstat (limited to 'ext/openssl/ossl_ts.c')
-rwxr-xr-x | ext/openssl/ossl_ts.c | 477 |
1 files changed, 289 insertions, 188 deletions
diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c index 1d9acdf8..01c423d7 100755 --- a/ext/openssl/ossl_ts.c +++ b/ext/openssl/ossl_ts.c @@ -41,6 +41,21 @@ } \ } while (0) +#define NewTSTokenInfo(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ts_token_info_type, 0) +#define SetTSTokenInfo(obj, info) do { \ + if (!(info)) { \ + ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \ + } \ + RTYPEDDATA_DATA(obj) = (info); \ +} while (0) +#define GetTSTokenInfo(obj, info) do { \ + TypedData_Get_Struct((obj), TS_TST_INFO, &ossl_ts_token_info_type, (info)); \ + if (!(info)) { \ + ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \ + } \ +} while (0) + #define ossl_tsfac_get_default_policy_id(o) rb_attr_get((o),rb_intern("@default_policy_id")) #define ossl_tsfac_get_serial_number(o) rb_attr_get((o),rb_intern("@serial_number")) #define ossl_tsfac_get_gen_time(o) rb_attr_get((o),rb_intern("@gen_time")) @@ -50,6 +65,7 @@ static VALUE mTimestamp; static VALUE eTimestampError; static VALUE cTimestampRequest; static VALUE cTimestampResponse; +static VALUE cTimestampTokenInfo; static VALUE cTimestampFactory; static ID sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE; static ID sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE; @@ -83,6 +99,20 @@ static const rb_data_type_t ossl_ts_resp_type = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, }; +static void +ossl_ts_token_info_free(void *ptr) +{ + TS_TST_INFO_free(ptr); +} + +static const rb_data_type_t ossl_ts_token_info_type = { + "OpenSSL/Timestamp/TokenInfo", + { + 0, ossl_ts_token_info_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, +}; + static VALUE asn1_to_der(void *template, int (*i2d)(void *template, unsigned char **pp)) { @@ -501,7 +531,9 @@ ossl_ts_resp_initialize(VALUE self, VALUE der) der = ossl_to_der_if_possible(der); in = ossl_obj2bio(&der); - if (!d2i_TS_RESP_bio(in, &ts_resp)) + ts_resp = d2i_TS_RESP_bio(in, &ts_resp); + BIO_free(in); + if (!ts_resp) ossl_raise(eTimestampError, "Error when decoding the timestamp response"); DATA_PTR(self) = ts_resp; @@ -652,198 +684,30 @@ ossl_ts_resp_get_token(VALUE self) } /* - * Returns the version number of the timestamp token. With compliant servers, - * this value should be +1+ if present. If status is GRANTED or - * GRANTED_WITH_MODS. - * - * call-seq: - * response.version -> Integer or nil - */ -static VALUE -ossl_ts_resp_get_version(VALUE self) -{ - TS_RESP *resp; - TS_TST_INFO *tst; - - GetTSResponse(self, resp); - if (!(tst = TS_RESP_get_tst_info(resp))) - return Qnil; - return LONG2NUM(TS_TST_INFO_get_version(tst)); -} - -/* - * Returns the timestamp policy object identifier of the policy this timestamp - * was created under. If status is GRANTED or GRANTED_WITH_MODS, this is never - * +nil+. - * - * ===Example: - * id = response.policy_id - * puts id -> "1.2.3.4.5" - * - * call-seq: - * response.policy_id -> string or nil - */ -static VALUE -ossl_ts_resp_get_policy_id(VALUE self) -{ - TS_RESP *resp; - TS_TST_INFO *tst; - - GetTSResponse(self, resp); - if (!(tst = TS_RESP_get_tst_info(resp))) - return Qnil; - return get_asn1obj(TS_TST_INFO_get_policy_id(tst)); -} - -/* - * Returns the 'short name' of the object identifier representing the algorithm - * that was used to derive the message imprint digest. For valid timestamps, - * this is the same value that was already given in the Request. If status is - * GRANTED or GRANTED_WITH_MODS, this is never +nil+. - * - * ===Example: - * algo = request.algorithm - * puts algo -> "SHA1" - * - * call-seq: - * response.algorithm -> string or nil - */ -static VALUE -ossl_ts_resp_get_algorithm(VALUE self) -{ - TS_RESP *resp; - TS_TST_INFO *tst; - TS_MSG_IMPRINT *mi; - X509_ALGOR *algo; - - GetTSResponse(self, resp); - if (!(tst = TS_RESP_get_tst_info(resp))) - return Qnil; - mi = TS_TST_INFO_get_msg_imprint(tst); - algo = TS_MSG_IMPRINT_get_algo(mi); - return get_asn1obj(algo->algorithm); -} - -/* - * Returns the message imprint digest. For valid timestamps, - * this is the same value that was already given in the Request. - * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+. - * - * ===Example: - * algo = request.algorithm - * puts algo -> "SHA1" - * - * call-seq: - * response.algorithm -> string or nil - */ -static VALUE -ossl_ts_resp_get_msg_imprint(VALUE self) -{ - TS_RESP *resp; - TS_TST_INFO *tst; - TS_MSG_IMPRINT *mi; - ASN1_OCTET_STRING *hashed_msg; - VALUE ret; - - GetTSResponse(self, resp); - if (!(tst = TS_RESP_get_tst_info(resp))) - return Qnil; - mi = TS_TST_INFO_get_msg_imprint(tst); - hashed_msg = TS_MSG_IMPRINT_get_msg(mi); - ret = rb_str_new((const char *)hashed_msg->data, hashed_msg->length); - - return ret; -} - -/* - * Returns serial number of the timestamp token. This value shall never be the - * same for two timestamp tokens issued by a dedicated timestamp authority. - * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+. + * Get the response's token info if present. * * call-seq: - * response.serial_number -> BN or nil + * response.token_info -> nil or OpenSSL::Timestamp::TokenInfo */ static VALUE -ossl_ts_resp_get_serial_number(VALUE self) +ossl_ts_resp_get_token_info(VALUE self) { TS_RESP *resp; - TS_TST_INFO *tst; + TS_TST_INFO *info, *copy; + VALUE obj; GetTSResponse(self, resp); - if (!(tst = TS_RESP_get_tst_info(resp))) + if (!(info = TS_RESP_get_tst_info(resp))) return Qnil; - return asn1integer_to_num(TS_TST_INFO_get_serial(tst)); -} - -/* - * Returns time when this timestamp token was created. If status is GRANTED or - * GRANTED_WITH_MODS, this is never +nil+. - * - * call-seq: - * response.gen_time -> Time - */ -static VALUE -ossl_ts_resp_get_gen_time(VALUE self) -{ - TS_RESP *resp; - TS_TST_INFO *tst; - GetTSResponse(self, resp); - if (!(tst = TS_RESP_get_tst_info(resp))) - return Qnil; - return asn1time_to_time(TS_TST_INFO_get_time(tst)); -} + obj = NewTSTokenInfo(cTimestampTokenInfo); -/* - * If the ordering field is missing, or if the ordering field is present - * and set to false, then the genTime field only indicates the time at - * which the time-stamp token has been created by the TSA. In such a - * case, the ordering of time-stamp tokens issued by the same TSA or - * different TSAs is only possible when the difference between the - * genTime of the first time-stamp token and the genTime of the second - * time-stamp token is greater than the sum of the accuracies of the - * genTime for each time-stamp token. - * - * If the ordering field is present and set to true, every time-stamp - * token from the same TSA can always be ordered based on the genTime - * field, regardless of the genTime accuracy. - * - * call-seq: - * response.ordering -> true, falses or nil - */ -static VALUE -ossl_ts_resp_get_ordering(VALUE self) -{ - TS_RESP *resp; - TS_TST_INFO *tst; - - GetTSResponse(self, resp); - if (!(tst = TS_RESP_get_tst_info(resp))) - return Qnil; - return TS_TST_INFO_get_ordering(tst) ? Qtrue : Qfalse; -} - -/* - * If the timestamp token is valid then this field contains the same nonce that - * was passed to the timestamp server in the initial Request. - * - * call-seq: - * response.nonce -> BN or nil - */ -static VALUE -ossl_ts_resp_get_nonce(VALUE self) -{ - TS_RESP *resp; - TS_TST_INFO *tst; - const ASN1_INTEGER *nonce; + if (!(copy = TS_TST_INFO_dup(info))) + ossl_raise(eTimestampError, NULL); - GetTSResponse(self, resp); - if (!(tst = TS_RESP_get_tst_info(resp))) - return Qnil; - if (!(nonce = TS_TST_INFO_get_nonce(tst))) - return Qnil; + SetTSTokenInfo(obj, copy); - return asn1integer_to_num(nonce); + return obj; } /* @@ -992,6 +856,233 @@ ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec) return 1; } +static VALUE +ossl_ts_token_info_alloc(VALUE klass) +{ + TS_TST_INFO *info; + VALUE obj; + + obj = NewTSTokenInfo(klass); + if (!(info = TS_TST_INFO_new())) + ossl_raise(eTimestampError, NULL); + SetTSTokenInfo(obj, info); + + return obj; +} + +/* + * Creates a TokenInfo from a +File+ or +string+ parameter, the + * corresponding +File+ or +string+ must be DER-encoded. Please note + * that TokenInfo is an immutable read-only class. If you'd like to create + * timestamps please refer to Factory instead. + * + * call-seq: + * OpenSSL::Timestamp::TokenInfo.new(file) -> token-info + * OpenSSL::Timestamp::TokenInfo.new(string) -> token-info + */ +static VALUE +ossl_ts_token_info_initialize(VALUE self, VALUE der) +{ + TS_TST_INFO *info = DATA_PTR(self); + BIO *in; + + der = ossl_to_der_if_possible(der); + in = ossl_obj2bio(&der); + info = d2i_TS_TST_INFO_bio(in, &info); + BIO_free(in); + if (!info) + ossl_raise(eTimestampError, "Error when decoding the timestamp token info"); + DATA_PTR(self) = info; + + return self; +} + +/* + * Returns the version number of the token info. With compliant servers, + * this value should be +1+ if present. If status is GRANTED or + * GRANTED_WITH_MODS. + * + * call-seq: + * token_info.version -> Integer or nil + */ +static VALUE +ossl_ts_token_info_get_version(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return LONG2NUM(TS_TST_INFO_get_version(info)); +} + +/* + * Returns the timestamp policy object identifier of the policy this timestamp + * was created under. If status is GRANTED or GRANTED_WITH_MODS, this is never + * +nil+. + * + * ===Example: + * id = token_info.policy_id + * puts id -> "1.2.3.4.5" + * + * call-seq: + * token_info.policy_id -> string or nil + */ +static VALUE +ossl_ts_token_info_get_policy_id(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return get_asn1obj(TS_TST_INFO_get_policy_id(info)); +} + +/* + * Returns the 'short name' of the object identifier representing the algorithm + * that was used to derive the message imprint digest. For valid timestamps, + * this is the same value that was already given in the Request. If status is + * GRANTED or GRANTED_WITH_MODS, this is never +nil+. + * + * ===Example: + * algo = token_info.algorithm + * puts algo -> "SHA1" + * + * call-seq: + * token_info.algorithm -> string or nil + */ +static VALUE +ossl_ts_token_info_get_algorithm(VALUE self) +{ + TS_TST_INFO *info; + TS_MSG_IMPRINT *mi; + X509_ALGOR *algo; + + GetTSTokenInfo(self, info); + mi = TS_TST_INFO_get_msg_imprint(info); + algo = TS_MSG_IMPRINT_get_algo(mi); + return get_asn1obj(algo->algorithm); +} + +/* + * Returns the message imprint digest. For valid timestamps, + * this is the same value that was already given in the Request. + * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+. + * + * ===Example: + * mi = token_info.msg_imprint + * puts mi -> "DEADBEEF" + * + * call-seq: + * token_info.msg_imprint -> string. + */ +static VALUE +ossl_ts_token_info_get_msg_imprint(VALUE self) +{ + TS_TST_INFO *info; + TS_MSG_IMPRINT *mi; + ASN1_OCTET_STRING *hashed_msg; + VALUE ret; + + GetTSTokenInfo(self, info); + mi = TS_TST_INFO_get_msg_imprint(info); + hashed_msg = TS_MSG_IMPRINT_get_msg(mi); + ret = rb_str_new((const char *)hashed_msg->data, hashed_msg->length); + + return ret; +} + +/* + * Returns serial number of the timestamp token. This value shall never be the + * same for two timestamp tokens issued by a dedicated timestamp authority. + * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+. + * + * call-seq: + * token_info.serial_number -> BN or nil + */ +static VALUE +ossl_ts_token_info_get_serial_number(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return asn1integer_to_num(TS_TST_INFO_get_serial(info)); +} + +/* + * Returns time when this timestamp token was created. If status is GRANTED or + * GRANTED_WITH_MODS, this is never +nil+. + * + * call-seq: + * token_info.gen_time -> Time + */ +static VALUE +ossl_ts_token_info_get_gen_time(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return asn1time_to_time(TS_TST_INFO_get_time(info)); +} + +/* + * If the ordering field is missing, or if the ordering field is present + * and set to false, then the genTime field only indicates the time at + * which the time-stamp token has been created by the TSA. In such a + * case, the ordering of time-stamp tokens issued by the same TSA or + * different TSAs is only possible when the difference between the + * genTime of the first time-stamp token and the genTime of the second + * time-stamp token is greater than the sum of the accuracies of the + * genTime for each time-stamp token. + * + * If the ordering field is present and set to true, every time-stamp + * token from the same TSA can always be ordered based on the genTime + * field, regardless of the genTime accuracy. + * + * call-seq: + * token_info.ordering -> true, falses or nil + */ +static VALUE +ossl_ts_token_info_get_ordering(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return TS_TST_INFO_get_ordering(info) ? Qtrue : Qfalse; +} + +/* + * If the timestamp token is valid then this field contains the same nonce that + * was passed to the timestamp server in the initial Request. + * + * call-seq: + * token_info.nonce -> BN or nil + */ +static VALUE +ossl_ts_token_info_get_nonce(VALUE self) +{ + TS_TST_INFO *info; + const ASN1_INTEGER *nonce; + + GetTSTokenInfo(self, info); + if (!(nonce = TS_TST_INFO_get_nonce(info))) + return Qnil; + + return asn1integer_to_num(nonce); +} + +/* + * Returns the TokenInfo in DER-encoded form. + * + * call-seq: + * token_info.to_der -> string + */ +static VALUE +ossl_ts_token_info_to_der(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return asn1_to_der((void *)info, (int (*)(void *, unsigned char **))i2d_TS_TST_INFO); +} + /* * Creates a Response with the help of an OpenSSL::PKey, an * OpenSSL::X509::Certificate and a Request. @@ -1228,18 +1319,28 @@ Init_ossl_ts(void) rb_define_method(cTimestampResponse, "failure_info", ossl_ts_resp_get_failure_info, 0); rb_define_method(cTimestampResponse, "status_text", ossl_ts_resp_get_status_text, 0); rb_define_method(cTimestampResponse, "token", ossl_ts_resp_get_token, 0); + rb_define_method(cTimestampResponse, "token_info", ossl_ts_resp_get_token_info, 0); rb_define_method(cTimestampResponse, "tsa_certificate", ossl_ts_resp_get_tsa_certificate, 0); - rb_define_method(cTimestampResponse, "version", ossl_ts_resp_get_version, 0); - rb_define_method(cTimestampResponse, "policy_id", ossl_ts_resp_get_policy_id, 0); - rb_define_method(cTimestampResponse, "algorithm", ossl_ts_resp_get_algorithm, 0); - rb_define_method(cTimestampResponse, "message_imprint", ossl_ts_resp_get_msg_imprint, 0); - rb_define_method(cTimestampResponse, "serial_number", ossl_ts_resp_get_serial_number, 0); - rb_define_method(cTimestampResponse, "gen_time", ossl_ts_resp_get_gen_time, 0); - rb_define_method(cTimestampResponse, "ordering", ossl_ts_resp_get_ordering, 0); - rb_define_method(cTimestampResponse, "nonce", ossl_ts_resp_get_nonce, 0); rb_define_method(cTimestampResponse, "to_der", ossl_ts_resp_to_der, 0); rb_define_method(cTimestampResponse, "verify", ossl_ts_resp_verify, -1); + /* Document-class: OpenSSL::Timestamp::TokenInfo + * Immutable and read-only representation of a timestamp token info from a + * Response. + */ + cTimestampTokenInfo = rb_define_class_under(mTimestamp, "TokenInfo", rb_cObject); + rb_define_alloc_func(cTimestampTokenInfo, ossl_ts_token_info_alloc); + rb_define_method(cTimestampTokenInfo, "initialize", ossl_ts_token_info_initialize, 1); + rb_define_method(cTimestampTokenInfo, "version", ossl_ts_token_info_get_version, 0); + rb_define_method(cTimestampTokenInfo, "policy_id", ossl_ts_token_info_get_policy_id, 0); + rb_define_method(cTimestampTokenInfo, "algorithm", ossl_ts_token_info_get_algorithm, 0); + rb_define_method(cTimestampTokenInfo, "message_imprint", ossl_ts_token_info_get_msg_imprint, 0); + rb_define_method(cTimestampTokenInfo, "serial_number", ossl_ts_token_info_get_serial_number, 0); + rb_define_method(cTimestampTokenInfo, "gen_time", ossl_ts_token_info_get_gen_time, 0); + rb_define_method(cTimestampTokenInfo, "ordering", ossl_ts_token_info_get_ordering, 0); + rb_define_method(cTimestampTokenInfo, "nonce", ossl_ts_token_info_get_nonce, 0); + rb_define_method(cTimestampTokenInfo, "to_der", ossl_ts_token_info_to_der, 0); + /* Document-class: OpenSSL::Timestamp::Request * Allows to create timestamp requests or parse existing ones. A Request is * also needed for creating timestamps from scratch with Factory. When |