instance method
OpenSSL::Timestamp::Factory#create_timestamp
(::OpenSSL::PKey::PKey key, ::OpenSSL::X509::Certificate cert, ::OpenSSL::Timestamp::Request request) -> ::OpenSSL::Timestamp::Response
factory.create_timestamp(key, certificate, request) → Response
ext/openssl/ossl_ts.c
View on GitHub ↗
static VALUE
ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
{
VALUE serial_number, def_policy_id, gen_time, additional_certs,
allowed_digests, allowed_digests_tmp = Qnil;
VALUE str;
STACK_OF(X509) *inter_certs;
VALUE tsresp, ret = Qnil;
EVP_PKEY *sign_key;
X509 *tsa_cert;
TS_REQ *req;
TS_RESP *response = NULL;
TS_RESP_CTX *ctx = NULL;
BIO *req_bio;
ASN1_INTEGER *asn1_serial = NULL;
ASN1_OBJECT *def_policy_id_obj = NULL;
long lgen_time;
const char * err_msg = NULL;
int status = 0;
tsresp = NewTSResponse(cTimestampResponse);
tsa_cert = GetX509CertPtr(certificate);
sign_key = GetPrivPKeyPtr(key);
GetTSRequest(request, req);
gen_time = ossl_tsfac_get_gen_time(self);
if (!rb_obj_is_instance_of(gen_time, rb_cTime)) {
err_msg = "@gen_time must be a Time.";
goto end;
}
lgen_time = NUM2LONG(rb_funcall(gen_time, rb_intern("to_i"), 0));
serial_number = ossl_tsfac_get_serial_number(self);
if (NIL_P(serial_number)) {
err_msg = "@serial_number must be set.";
goto end;
}
asn1_serial = num_to_asn1integer(serial_number, NULL);
def_policy_id = ossl_tsfac_get_default_policy_id(self);
if (NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
err_msg = "No policy id in the request and no default policy set";
goto end;
}
if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
def_policy_id_obj = (ASN1_OBJECT*)rb_protect(obj_to_asn1obj_i, (VALUE)def_policy_id, &status);
if (status)
goto end;
}
if (!(ctx = TS_RESP_CTX_new())) {
err_msg = "Memory allocation failed.";
goto end;
}
TS_RESP_CTX_set_serial_cb(ctx, ossl_tsfac_serial_cb, &asn1_serial);
if (!TS_RESP_CTX_set_signer_cert(ctx, tsa_cert)) {
err_msg = "Certificate does not contain the timestamping extension";
goto end;
}
additional_certs = ossl_tsfac_get_additional_certs(self);
if (rb_obj_is_kind_of(additional_certs, rb_cArray)) {
inter_certs = ossl_protect_x509_ary2sk(additional_certs, &status);
if (status)
goto end;
/* this dups the sk_X509 and ups each cert's ref count */
TS_RESP_CTX_set_certs(ctx, inter_certs);
sk_X509_pop_free(inter_certs, X509_free);
}
TS_RESP_CTX_set_signer_key(ctx, sign_key);
if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req))
TS_RESP_CTX_set_def_policy(ctx, def_policy_id_obj);
if (TS_REQ_get_policy_id(req))
TS_RESP_CTX_set_def_policy(ctx, TS_REQ_get_policy_id(req));
TS_RESP_CTX_set_time_cb(ctx, ossl_tsfac_time_cb, &lgen_time);
allowed_digests = ossl_tsfac_get_allowed_digests(self);
if (rb_obj_is_kind_of(allowed_digests, rb_cArray)) {
allowed_digests_tmp = rb_ary_new_capa(RARRAY_LEN(allowed_digests));
for (long i = 0; i < RARRAY_LEN(allowed_digests); i++) {
VALUE args[] = {
allowed_digests_tmp,
rb_ary_entry(allowed_digests, i),
};
const EVP_MD *md = (const EVP_MD *)rb_protect(ossl_evp_md_fetch_i,
(VALUE)args, &status);
if (status)
goto end;
if (!TS_RESP_CTX_add_md(ctx, md))
goto end;
}
}
str = rb_protect(ossl_to_der, request, &status);
if (status)
goto end;
req_bio = (BIO*)rb_protect(ossl_obj2bio_i, (VALUE)&str, &status);
if (status)
goto end;
response = TS_RESP_create_response(ctx, req_bio);
BIO_free(req_bio);
RB_GC_GUARD(allowed_digests_tmp);
if (!response) {
err_msg = "Error during response generation";
goto end;
}
/* bad responses aren't exceptional, but openssl still sets error
* information. */
ossl_clear_error();
SetTSResponse(tsresp, response);
ret = tsresp;
end:
ASN1_INTEGER_free(asn1_serial);
ASN1_OBJECT_free(def_policy_id_obj);
TS_RESP_CTX_free(ctx);
if (err_msg)
rb_exc_raise(ossl_make_error(eTimestampError, rb_str_new_cstr(err_msg)));
if (status)
rb_jump_tag(status);
return ret;
}
Creates a Response with the help of an OpenSSL::PKey, an OpenSSL::X509::Certificate and a Request.
Mandatory parameters for timestamp creation that need to be set in the Request:
Mandatory parameters that need to be set in the Factory:
In addition one of either Request#policy_id or Factory#default_policy_id must be set.
Raises a TimestampError if creation fails, though successfully created error responses may be returned.