# class OpenSSL::OCSP::BasicResponse

An `OpenSSL::OCSP::BasicResponse` contains the status of a certificate check which is created from an `OpenSSL::OCSP::Request`. A `BasicResponse` is more detailed than a `Response`.

### Public Class Methods

OpenSSL::OCSP::BasicResponse.new(der_string = nil) → basic_response
Source

    static VALUE
    ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self)
    {
        VALUE arg;
        OCSP_BASICRESP *res, *res_new;
        const unsigned char *p;

        rb_scan_args(argc, argv, "01", &arg);
        if (!NIL_P(arg)) {
            GetOCSPBasicRes(self, res);
            arg = ossl_to_der_if_possible(arg);
            StringValue(arg);
            p = (unsigned char *)RSTRING_PTR(arg);
            res_new = d2i_OCSP_BASICRESP(NULL, &p, RSTRING_LEN(arg));
            if (!res_new)
                ossl_raise(eOCSPError, "d2i_OCSP_BASICRESP");
            SetOCSPBasicRes(self, res_new);
            OCSP_BASICRESP_free(res);
        }

        return self;
    }

Creates a new `BasicResponse`. If der_string is given, decodes der_string as DER.

### Public Instance Methods

add_nonce(nonce = nil)
Source

    static VALUE
    ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
    {
        OCSP_BASICRESP *bs;
        VALUE val;
        int ret;

        rb_scan_args(argc, argv, "01", &val);
        if(NIL_P(val)) {
            GetOCSPBasicRes(self, bs);
            ret = OCSP_basic_add1_nonce(bs, NULL, -1);
        }
        else{
            StringValue(val);
            GetOCSPBasicRes(self, bs);
            ret = OCSP_basic_add1_nonce(bs, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
        }
        if(!ret) ossl_raise(eOCSPError, NULL);

        return self;
    }

Adds nonce to this response. If no nonce was provided a random nonce will be added.

add_status(certificate_id, status, reason, revocation_time, this_update, next_update, extensions) → basic_response
Source

    static VALUE
    ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
                             VALUE reason, VALUE revtime,
                             VALUE thisupd, VALUE nextupd, VALUE ext)
    {
        OCSP_BASICRESP *bs;
        OCSP_SINGLERESP *single;
        OCSP_CERTID *id;
        ASN1_TIME *ths = NULL, *nxt = NULL, *rev = NULL;
        int st, rsn = 0, error = 0, rstatus = 0;
        long i;
        VALUE tmp;

        GetOCSPBasicRes(self, bs);
        GetOCSPCertId(cid, id);
        st = NUM2INT(status);
        if (!NIL_P(ext)) { /* All ext's members must be X509::Extension */
            ext = rb_check_array_type(ext);
            for (i = 0; i < RARRAY_LEN(ext); i++)
                OSSL_Check_Kind(RARRAY_AREF(ext, i), cX509Ext);
        }

        if (st == V_OCSP_CERTSTATUS_REVOKED) {
            rsn = NUM2INT(reason);
            tmp = rb_protect(add_status_convert_time, revtime, &rstatus);
            if (rstatus) goto err;
            rev = (ASN1_TIME *)tmp;
        }

        tmp = rb_protect(add_status_convert_time, thisupd, &rstatus);
        if (rstatus) goto err;
        ths = (ASN1_TIME *)tmp;

        if (!NIL_P(nextupd)) {
            tmp = rb_protect(add_status_convert_time, nextupd, &rstatus);
            if (rstatus) goto err;
            nxt = (ASN1_TIME *)tmp;
        }

        if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){
            error = 1;
            goto err;
        }

        if(!NIL_P(ext)){
            X509_EXTENSION *x509ext;

            for(i = 0; i < RARRAY_LEN(ext); i++){
                x509ext = GetX509ExtPtr(RARRAY_AREF(ext, i));
                if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
                    error = 1;
                    goto err;
                }
            }
        }

     err:
        ASN1_TIME_free(ths);
        ASN1_TIME_free(nxt);
        ASN1_TIME_free(rev);
        if(error) ossl_raise(eOCSPError, NULL);
        if(rstatus) rb_jump_tag(rstatus);

        return self;
    }

Adds a certificate status for certificate_id. status is the status, and must be one of these:

- OpenSSL::OCSP::V_CERTSTATUS_GOOD

- OpenSSL::OCSP::V_CERTSTATUS_REVOKED

- OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN

reason and revocation_time can be given only when status is OpenSSL::OCSP::V_CERTSTATUS_REVOKED. reason describes the reason for the revocation, and must be one of OpenSSL::OCSP::REVOKED_STATUS_* constants. revocation_time is the time when the certificate is revoked.

this_update and next_update indicate the time at which the status is verified to be correct and the time at or before which newer information will be available, respectively. next_update is optional.

extensions is an `Array` of `OpenSSL::X509::Extension` to be included in the `SingleResponse`. This is also optional.

Note that the times, revocation_time, this_update and next_update can be specified in either of `Integer` or `Time` object. If they are `Integer`, it is treated as the relative seconds from the current time.

copy_nonce(request) → Integer
Source

    static VALUE
    ossl_ocspbres_copy_nonce(VALUE self, VALUE request)
    {
        OCSP_BASICRESP *bs;
        OCSP_REQUEST *req;
        int ret;

        GetOCSPBasicRes(self, bs);
        GetOCSPReq(request, req);
        ret = OCSP_copy_nonce(bs, req);

        return INT2NUM(ret);
    }

Copies the nonce from request into this response. Returns 1 on success and 0 on failure.

find_response(certificate_id) → SingleResponse | nil
Source

    static VALUE
    ossl_ocspbres_find_response(VALUE self, VALUE target)
    {
        OCSP_BASICRESP *bs;
        OCSP_SINGLERESP *sres, *sres_new;
        OCSP_CERTID *id;
        int n;

        GetOCSPCertId(target, id);
        GetOCSPBasicRes(self, bs);

        if ((n = OCSP_resp_find(bs, id, -1)) == -1)
            return Qnil;

        sres = OCSP_resp_get0(bs, n);
        sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres);
        if (!sres_new)
            ossl_raise(eOCSPError, "ASN1_item_dup");

        return ossl_ocspsres_new(sres_new);
    }

Returns a `SingleResponse` whose CertId matches with certificate_id, or `nil` if this `BasicResponse` does not contain it.

initialize_copy (p1)
Source

    static VALUE
    ossl_ocspbres_initialize_copy(VALUE self, VALUE other)
    {
        OCSP_BASICRESP *bs, *bs_old, *bs_new;

        rb_check_frozen(self);
        GetOCSPBasicRes(self, bs_old);
        GetOCSPBasicRes(other, bs);

        bs_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_BASICRESP), bs);
        if (!bs_new)
            ossl_raise(eOCSPError, "ASN1_item_dup");

        SetOCSPBasicRes(self, bs_new);
        OCSP_BASICRESP_free(bs_old);

        return self;
    }

responses → Array of SingleResponse
Source

    static VALUE
    ossl_ocspbres_get_responses(VALUE self)
    {
        OCSP_BASICRESP *bs;
        VALUE ret;
        int count, i;

        GetOCSPBasicRes(self, bs);
        count = OCSP_resp_count(bs);
        ret = rb_ary_new2(count);

        for (i = 0; i < count; i++) {
            OCSP_SINGLERESP *sres, *sres_new;

            sres = OCSP_resp_get0(bs, i);
            sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres);
            if (!sres_new)
                ossl_raise(eOCSPError, "ASN1_item_dup");

            rb_ary_push(ret, ossl_ocspsres_new(sres_new));
        }

        return ret;
    }

Returns an `Array` of `SingleResponse` for this `BasicResponse`.

sign(cert, key, certs = nil, flags = 0, digest = nil) → self
Source

    static VALUE
    ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
    {
        VALUE signer_cert, signer_key, certs, flags, digest;
        OCSP_BASICRESP *bs;
        X509 *signer;
        EVP_PKEY *key;
        STACK_OF(X509) *x509s = NULL;
        unsigned long flg = 0;
        const EVP_MD *md;
        int ret;

        rb_scan_args(argc, argv, "23", &signer_cert, &signer_key, &certs, &flags, &digest);
        GetOCSPBasicRes(self, bs);
        signer = GetX509CertPtr(signer_cert);
        key = GetPrivPKeyPtr(signer_key);
        if (!NIL_P(flags))
            flg = NUM2INT(flags);
        if (NIL_P(digest))
            md = NULL;
        else
            md = ossl_evp_get_digestbyname(digest);
        if (NIL_P(certs))
            flg |= OCSP_NOCERTS;
        else
            x509s = ossl_x509_ary2sk(certs);

        ret = OCSP_basic_sign(bs, signer, key, md, x509s, flg);
        sk_X509_pop_free(x509s, X509_free);
        if (!ret) ossl_raise(eOCSPError, NULL);

        return self;
    }

Signs this `OCSP` response using the cert, key and optional digest. This behaves in the similar way as `OpenSSL::OCSP::Request#sign`.

flags can include:

OpenSSL::OCSP::NOCERTS

  don’t include certificates

OpenSSL::OCSP::NOTIME

  don’t set producedAt

OpenSSL::OCSP::RESPID_KEY

  use signer’s public key hash as responderID

status → statuses
Source

    static VALUE
    ossl_ocspbres_get_status(VALUE self)
    {
        OCSP_BASICRESP *bs;
        OCSP_SINGLERESP *single;
        OCSP_CERTID *cid;
        ASN1_TIME *revtime, *thisupd, *nextupd;
        int status, reason;
        X509_EXTENSION *x509ext;
        VALUE ret, ary, ext;
        int count, ext_count, i, j;

        GetOCSPBasicRes(self, bs);
        ret = rb_ary_new();
        count = OCSP_resp_count(bs);
        for(i = 0; i < count; i++){
            single = OCSP_resp_get0(bs, i);
            if(!single) continue;

            revtime = thisupd = nextupd = NULL;
            status = OCSP_single_get0_status(single, &reason, &revtime,
                                             &thisupd, &nextupd);
            if(status < 0) continue;
            if(!(cid = OCSP_CERTID_dup((OCSP_CERTID *)OCSP_SINGLERESP_get0_id(single)))) /* FIXME */
                ossl_raise(eOCSPError, NULL);
            ary = rb_ary_new();
            rb_ary_push(ary, ossl_ocspcertid_new(cid));
            rb_ary_push(ary, INT2NUM(status));
            rb_ary_push(ary, INT2NUM(reason));
            rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil);
            rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil);
            rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil);
            ext = rb_ary_new();
            ext_count = OCSP_SINGLERESP_get_ext_count(single);
            for(j = 0; j < ext_count; j++){
                x509ext = OCSP_SINGLERESP_get_ext(single, j);
                rb_ary_push(ext, ossl_x509ext_new(x509ext));
            }
            rb_ary_push(ary, ext);
            rb_ary_push(ret, ary);
        }

        return ret;
    }

Returns an `Array` of statuses for this response. Each status contains a `CertificateId`, the status (0 for good, 1 for revoked, 2 for unknown), the reason for the status, the revocation time, the time of this update, the time for the next update and a list of `OpenSSL::X509::Extension`.

This should be superseded by `BasicResponse#responses` and `find_response` that return `SingleResponse`.

to_der → String
Source

    static VALUE
    ossl_ocspbres_to_der(VALUE self)
    {
        OCSP_BASICRESP *res;
        VALUE str;
        long len;
        unsigned char *p;

        GetOCSPBasicRes(self, res);
        if ((len = i2d_OCSP_BASICRESP(res, NULL)) <= 0)
            ossl_raise(eOCSPError, NULL);
        str = rb_str_new(0, len);
        p = (unsigned char *)RSTRING_PTR(str);
        if (i2d_OCSP_BASICRESP(res, &p) <= 0)
            ossl_raise(eOCSPError, NULL);
        ossl_str_adjust(str, p);

        return str;
    }

Encodes this basic response into a DER-encoded string.

verify(certificates, store, flags = 0) → true or false
Source

    static VALUE
    ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self)
    {
        VALUE certs, store, flags;
        OCSP_BASICRESP *bs;
        STACK_OF(X509) *x509s;
        X509_STORE *x509st;
        int flg, result;

        rb_scan_args(argc, argv, "21", &certs, &store, &flags);
        GetOCSPBasicRes(self, bs);
        x509st = GetX509StorePtr(store);
        flg = NIL_P(flags) ? 0 : NUM2INT(flags);
        x509s = ossl_x509_ary2sk(certs);
        result = OCSP_basic_verify(bs, x509s, x509st, flg);
        sk_X509_pop_free(x509s, X509_free);
        if (result <= 0)
            ossl_clear_error();

        return result > 0 ? Qtrue : Qfalse;
    }

Verifies the signature of the response using the given certificates and store. This works in the similar way as `OpenSSL::OCSP::Request#verify`.