# class OpenSSL::PKCS7

### Constants

Signer

### Attributes

data [R]
error_string [RW]

### Public Class Methods

encrypt(certs, data, cipher, flags = 0) → pkcs7
Source

    static VALUE
    ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
    {
        VALUE certs, data, cipher, flags;
        STACK_OF(X509) *x509s;
        BIO *in;
        const EVP_CIPHER *ciph;
        int flg, status = 0;
        VALUE ret;
        PKCS7 *p7;

        rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags);
        if (NIL_P(cipher)) {
            rb_raise(rb_eArgError,
                     "cipher must be specified. Before version 3.3, " \
                     "the default cipher was RC2-40-CBC.");
        }
        ciph = ossl_evp_get_cipherbyname(cipher);
        flg = NIL_P(flags) ? 0 : NUM2INT(flags);
        ret = NewPKCS7(cPKCS7);
        in = ossl_obj2bio(&data);
        x509s = ossl_protect_x509_ary2sk(certs, &status);
        if(status){
            BIO_free(in);
            rb_jump_tag(status);
        }
        if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){
            BIO_free(in);
            sk_X509_pop_free(x509s, X509_free);
            ossl_raise(ePKCS7Error, NULL);
        }
        BIO_free(in);
        SetPKCS7(ret, p7);
        ossl_pkcs7_set_data(ret, data);
        sk_X509_pop_free(x509s, X509_free);

        return ret;
    }

Creates a PKCS #7 enveloped-data structure.

Before version 3.3.0, `cipher` was optional and defaulted to `"RC2-40-CBC"`.

See also the man page PKCS7_encrypt(3).

new → pkcs7
new(string) → pkcs7
Source

    static VALUE
    ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
    {
        PKCS7 *p7, *p7_orig = RTYPEDDATA_DATA(self);
        BIO *in;
        VALUE arg;

        if(rb_scan_args(argc, argv, "01", &arg) == 0)
            return self;
        arg = ossl_to_der_if_possible(arg);
        in = ossl_obj2bio(&arg);
        p7 = d2i_PKCS7_bio(in, NULL);
        if (!p7) {
            OSSL_BIO_reset(in);
            p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
        }
        BIO_free(in);
        if (!p7)
            ossl_raise(rb_eArgError, "Could not parse the PKCS7");
        if (!p7->d.ptr) {
            PKCS7_free(p7);
            ossl_raise(rb_eArgError, "No content in PKCS7");
        }

        RTYPEDDATA_DATA(self) = p7;
        PKCS7_free(p7_orig);
        ossl_pkcs7_set_data(self, Qnil);
        ossl_pkcs7_set_err_string(self, Qnil);

        return self;
    }

Many methods in this class aren’t documented.

read_smime(string) → pkcs7
Source

    static VALUE
    ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
    {
        BIO *in, *out;
        PKCS7 *pkcs7;
        VALUE ret, data;

        ret = NewPKCS7(cPKCS7);
        in = ossl_obj2bio(&arg);
        out = NULL;
        pkcs7 = SMIME_read_PKCS7(in, &out);
        BIO_free(in);
        if (!pkcs7)
            ossl_raise(ePKCS7Error, "Could not parse the PKCS7");
        if (!pkcs7->d.ptr) {
            PKCS7_free(pkcs7);
            ossl_raise(ePKCS7Error, "No content in PKCS7");
        }

        data = out ? ossl_membio2str(out) : Qnil;
        SetPKCS7(ret, pkcs7);
        ossl_pkcs7_set_data(ret, data);
        ossl_pkcs7_set_err_string(ret, Qnil);

        return ret;
    }

sign(cert, key, data, [, certs [, flags]]) → pkcs7
Source

    static VALUE
    ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
    {
        VALUE cert, key, data, certs, flags;
        X509 *x509;
        EVP_PKEY *pkey;
        BIO *in;
        STACK_OF(X509) *x509s;
        int flg, status = 0;
        PKCS7 *pkcs7;
        VALUE ret;

        rb_scan_args(argc, argv, "32", &cert, &key, &data, &certs, &flags);
        x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
        pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
        flg = NIL_P(flags) ? 0 : NUM2INT(flags);
        ret = NewPKCS7(cPKCS7);
        in = ossl_obj2bio(&data);
        if(NIL_P(certs)) x509s = NULL;
        else{
            x509s = ossl_protect_x509_ary2sk(certs, &status);
            if(status){
                BIO_free(in);
                rb_jump_tag(status);
            }
        }
        if(!(pkcs7 = PKCS7_sign(x509, pkey, x509s, in, flg))){
            BIO_free(in);
            sk_X509_pop_free(x509s, X509_free);
            ossl_raise(ePKCS7Error, NULL);
        }
        SetPKCS7(ret, pkcs7);
        ossl_pkcs7_set_data(ret, data);
        ossl_pkcs7_set_err_string(ret, Qnil);
        BIO_free(in);
        sk_X509_pop_free(x509s, X509_free);

        return ret;
    }

write_smime(pkcs7 [, data [, flags]]) → string
Source

    static VALUE
    ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
    {
        VALUE pkcs7, data, flags;
        BIO *out, *in;
        PKCS7 *p7;
        VALUE str;
        int flg;

        rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags);
        flg = NIL_P(flags) ? 0 : NUM2INT(flags);
        if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7);
        GetPKCS7(pkcs7, p7);
        if(!NIL_P(data) && PKCS7_is_detached(p7))
            flg |= PKCS7_DETACHED;
        in = NIL_P(data) ? NULL : ossl_obj2bio(&data);
        if(!(out = BIO_new(BIO_s_mem()))){
            BIO_free(in);
            ossl_raise(ePKCS7Error, NULL);
        }
        if(!SMIME_write_PKCS7(out, p7, in, flg)){
            BIO_free(out);
            BIO_free(in);
            ossl_raise(ePKCS7Error, NULL);
        }
        BIO_free(in);
        str = ossl_membio2str(out);

        return str;
    }

### Public Instance Methods

add_certificate (p1)
Source

    static VALUE
    ossl_pkcs7_add_certificate(VALUE self, VALUE cert)
    {
        PKCS7 *pkcs7;
        X509 *x509;

        GetPKCS7(self, pkcs7);
        x509 = GetX509CertPtr(cert);  /* NO NEED TO DUP */
        if (!PKCS7_add_certificate(pkcs7, x509)){
            ossl_raise(ePKCS7Error, NULL);
        }

        return self;
    }

add_crl (p1)
Source

    static VALUE
    ossl_pkcs7_add_crl(VALUE self, VALUE crl)
    {
        PKCS7 *pkcs7;
        X509_CRL *x509crl;

        GetPKCS7(self, pkcs7); /* NO DUP needed! */
        x509crl = GetX509CRLPtr(crl);
        if (!PKCS7_add_crl(pkcs7, x509crl)) {
            ossl_raise(ePKCS7Error, NULL);
        }

        return self;
    }

add_data (p1)
Source

    static VALUE
    ossl_pkcs7_add_data(VALUE self, VALUE data)
    {
        PKCS7 *pkcs7;
        BIO *out, *in;
        char buf[4096];
        int len;

        GetPKCS7(self, pkcs7);
        if(PKCS7_type_is_signed(pkcs7)){
            if(!PKCS7_content_new(pkcs7, NID_pkcs7_data))
                ossl_raise(ePKCS7Error, NULL);
        }
        in = ossl_obj2bio(&data);
        if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err;
        for(;;){
            if((len = BIO_read(in, buf, sizeof(buf))) <= 0)
                break;
            if(BIO_write(out, buf, len) != len)
                goto err;
        }
        if(!PKCS7_dataFinal(pkcs7, out)) goto err;
        ossl_pkcs7_set_data(self, Qnil);

     err:
        BIO_free_all(out);
        BIO_free(in);
        if(ERR_peek_error()){
            ossl_raise(ePKCS7Error, NULL);
        }

        return data;
    }

Also aliased as: data=
add_recipient (p1)
Source

    static VALUE
    ossl_pkcs7_add_recipient(VALUE self, VALUE recip)
    {
        PKCS7 *pkcs7;
        PKCS7_RECIP_INFO *ri, *ri_new;

        GetPKCS7(self, pkcs7);
        GetPKCS7ri(recip, ri);

        ri_new = ossl_PKCS7_RECIP_INFO_dup(ri);
        if (!ri_new)
            ossl_raise(ePKCS7Error, "PKCS7_RECIP_INFO_dup");

        if (PKCS7_add_recipient_info(pkcs7, ri_new) != 1) {
            PKCS7_RECIP_INFO_free(ri_new);
            ossl_raise(ePKCS7Error, "PKCS7_add_recipient_info");
        }

        return self;
    }

add_signer (p1)
Source

    static VALUE
    ossl_pkcs7_add_signer(VALUE self, VALUE signer)
    {
        PKCS7 *pkcs7;
        PKCS7_SIGNER_INFO *si, *si_new;

        GetPKCS7(self, pkcs7);
        GetPKCS7si(signer, si);

        si_new = ossl_PKCS7_SIGNER_INFO_dup(si);
        if (!si_new)
            ossl_raise(ePKCS7Error, "PKCS7_SIGNER_INFO_dup");

        if (PKCS7_add_signer(pkcs7, si_new) != 1) {
            PKCS7_SIGNER_INFO_free(si_new);
            ossl_raise(ePKCS7Error, "PKCS7_add_signer");
        }

        return self;
    }

certificates ()
Source

    static VALUE
    ossl_pkcs7_get_certificates(VALUE self)
    {
        return ossl_x509_sk2ary(pkcs7_get_certs(self));
    }

certificates= (p1)
Source

    static VALUE
    ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
    {
        STACK_OF(X509) *certs;
        X509 *cert;

        certs = pkcs7_get_certs(self);
        while((cert = sk_X509_pop(certs))) X509_free(cert);
        rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);

        return ary;
    }

cipher= (p1)
Source

    static VALUE
    ossl_pkcs7_set_cipher(VALUE self, VALUE cipher)
    {
        PKCS7 *pkcs7;

        GetPKCS7(self, pkcs7);
        if (!PKCS7_set_cipher(pkcs7, ossl_evp_get_cipherbyname(cipher))) {
            ossl_raise(ePKCS7Error, NULL);
        }

        return cipher;
    }

crls ()
Source

    static VALUE
    ossl_pkcs7_get_crls(VALUE self)
    {
        return ossl_x509crl_sk2ary(pkcs7_get_crls(self));
    }

crls= (p1)
Source

    static VALUE
    ossl_pkcs7_set_crls(VALUE self, VALUE ary)
    {
        STACK_OF(X509_CRL) *crls;
        X509_CRL *crl;

        crls = pkcs7_get_crls(self);
        while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
        rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self);

        return ary;
    }

data= (p1)
Alias for: add_data
decrypt (p1, p2 = v2, p3 = v3)
Source

    static VALUE
    ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self)
    {
        VALUE pkey, cert, flags;
        EVP_PKEY *key;
        X509 *x509;
        int flg;
        PKCS7 *p7;
        BIO *out;
        VALUE str;

        rb_scan_args(argc, argv, "12", &pkey, &cert, &flags);
        key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */
        x509 = NIL_P(cert) ? NULL : GetX509CertPtr(cert); /* NO NEED TO DUP */
        flg = NIL_P(flags) ? 0 : NUM2INT(flags);
        GetPKCS7(self, p7);
        if(!(out = BIO_new(BIO_s_mem())))
            ossl_raise(ePKCS7Error, NULL);
        if(!PKCS7_decrypt(p7, key, x509, out, flg)){
            BIO_free(out);
            ossl_raise(ePKCS7Error, NULL);
        }
        str = ossl_membio2str(out); /* out will be free */

        return str;
    }

detached ()
Source

    static VALUE
    ossl_pkcs7_get_detached(VALUE self)
    {
        PKCS7 *p7;
        GetPKCS7(self, p7);
        return PKCS7_get_detached(p7) ? Qtrue : Qfalse;
    }

detached= (p1)
Source

    static VALUE
    ossl_pkcs7_set_detached(VALUE self, VALUE flag)
    {
        PKCS7 *p7;

        GetPKCS7(self, p7);
        if(flag != Qtrue && flag != Qfalse)
            ossl_raise(ePKCS7Error, "must specify a boolean");
        if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0))
            ossl_raise(ePKCS7Error, NULL);

        return flag;
    }

detached? ()
Source

    static VALUE
    ossl_pkcs7_detached_p(VALUE self)
    {
        PKCS7 *p7;
        GetPKCS7(self, p7);
        return PKCS7_is_detached(p7) ? Qtrue : Qfalse;
    }

initialize_copy (p1)
Source

    static VALUE
    ossl_pkcs7_copy(VALUE self, VALUE other)
    {
        PKCS7 *a, *b, *pkcs7;

        rb_check_frozen(self);
        if (self == other) return self;

        GetPKCS7(self, a);
        GetPKCS7(other, b);

        pkcs7 = PKCS7_dup(b);
        if (!pkcs7) {
            ossl_raise(ePKCS7Error, NULL);
        }
        DATA_PTR(self) = pkcs7;
        PKCS7_free(a);

        return self;
    }

recipients ()
Source

    static VALUE
    ossl_pkcs7_get_recipient(VALUE self)
    {
        PKCS7 *pkcs7;
        STACK_OF(PKCS7_RECIP_INFO) *sk;
        PKCS7_RECIP_INFO *si;
        int num, i;
        VALUE ary;

        GetPKCS7(self, pkcs7);
        if (PKCS7_type_is_enveloped(pkcs7))
            sk = pkcs7->d.enveloped->recipientinfo;
        else if (PKCS7_type_is_signedAndEnveloped(pkcs7))
            sk = pkcs7->d.signed_and_enveloped->recipientinfo;
        else sk = NULL;
        if (!sk) return rb_ary_new();
        if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) {
            ossl_raise(ePKCS7Error, "Negative number of recipient!");
        }
        ary = rb_ary_new2(num);
        for (i=0; i<num; i++) {
            si = sk_PKCS7_RECIP_INFO_value(sk, i);
            rb_ary_push(ary, ossl_pkcs7ri_new(si));
        }

        return ary;
    }

signers ()
Source

    static VALUE
    ossl_pkcs7_get_signer(VALUE self)
    {
        PKCS7 *pkcs7;
        STACK_OF(PKCS7_SIGNER_INFO) *sk;
        PKCS7_SIGNER_INFO *si;
        int num, i;
        VALUE ary;

        GetPKCS7(self, pkcs7);
        if (!(sk = PKCS7_get_signer_info(pkcs7))) {
            OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!");
            return rb_ary_new();
        }
        if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) {
            ossl_raise(ePKCS7Error, "Negative number of signers!");
        }
        ary = rb_ary_new2(num);
        for (i=0; i<num; i++) {
            si = sk_PKCS7_SIGNER_INFO_value(sk, i);
            rb_ary_push(ary, ossl_pkcs7si_new(si));
        }

        return ary;
    }

to_der ()
Source

    static VALUE
    ossl_pkcs7_to_der(VALUE self)
    {
        PKCS7 *pkcs7;
        VALUE str;
        long len;
        unsigned char *p;

        GetPKCS7(self, pkcs7);
        if((len = i2d_PKCS7(pkcs7, NULL)) <= 0)
            ossl_raise(ePKCS7Error, NULL);
        str = rb_str_new(0, len);
        p = (unsigned char *)RSTRING_PTR(str);
        if(i2d_PKCS7(pkcs7, &p) <= 0)
            ossl_raise(ePKCS7Error, NULL);
        ossl_str_adjust(str, p);

        return str;
    }

to_pem ()
Source

    static VALUE
    ossl_pkcs7_to_pem(VALUE self)
    {
        PKCS7 *pkcs7;
        BIO *out;
        VALUE str;

        GetPKCS7(self, pkcs7);
        if (!(out = BIO_new(BIO_s_mem()))) {
            ossl_raise(ePKCS7Error, NULL);
        }
        if (!PEM_write_bio_PKCS7(out, pkcs7)) {
            BIO_free(out);
            ossl_raise(ePKCS7Error, NULL);
        }
        str = ossl_membio2str(out);

        return str;
    }

Also aliased as: to_s
to_s ()
Alias for: to_pem
to_text ()
Source

    static VALUE
    ossl_pkcs7_to_text(VALUE self)
    {
        PKCS7 *pkcs7;
        BIO *out;
        VALUE str;

        GetPKCS7(self, pkcs7);
        if(!(out = BIO_new(BIO_s_mem())))
            ossl_raise(ePKCS7Error, NULL);
        if(!PKCS7_print_ctx(out, pkcs7, 0, NULL)) {
            BIO_free(out);
            ossl_raise(ePKCS7Error, NULL);
        }
        str = ossl_membio2str(out);

        return str;
    }

type → string or nil
Source

    static VALUE
    ossl_pkcs7_get_type(VALUE self)
    {
        PKCS7 *p7;

        GetPKCS7(self, p7);
        if(PKCS7_type_is_signed(p7))
            return ID2SYM(rb_intern("signed"));
        if(PKCS7_type_is_encrypted(p7))
            return ID2SYM(rb_intern("encrypted"));
        if(PKCS7_type_is_enveloped(p7))
            return ID2SYM(rb_intern("enveloped"));
        if(PKCS7_type_is_signedAndEnveloped(p7))
            return ID2SYM(rb_intern("signedAndEnveloped"));
        if(PKCS7_type_is_data(p7))
            return ID2SYM(rb_intern("data"));
        return Qnil;
    }

type = type → type
Source

    static VALUE
    ossl_pkcs7_set_type(VALUE self, VALUE type)
    {
        PKCS7 *p7;

        GetPKCS7(self, p7);
        if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type)))
            ossl_raise(ePKCS7Error, NULL);

        return type;
    }

verify (p1, p2, p3 = v3, p4 = v4)
Source

    static VALUE
    ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
    {
        VALUE certs, store, indata, flags;
        STACK_OF(X509) *x509s;
        X509_STORE *x509st;
        int flg, ok, status = 0;
        BIO *in, *out;
        PKCS7 *p7;
        VALUE data;
        const char *msg;

        GetPKCS7(self, p7);
        rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags);
        x509st = GetX509StorePtr(store);
        flg = NIL_P(flags) ? 0 : NUM2INT(flags);
        if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self);
        in = NIL_P(indata) ? NULL : ossl_obj2bio(&indata);
        if(NIL_P(certs)) x509s = NULL;
        else{
            x509s = ossl_protect_x509_ary2sk(certs, &status);
            if(status){
                BIO_free(in);
                rb_jump_tag(status);
            }
        }
        if(!(out = BIO_new(BIO_s_mem()))){
            BIO_free(in);
            sk_X509_pop_free(x509s, X509_free);
            ossl_raise(ePKCS7Error, NULL);
        }
        ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
        BIO_free(in);
        sk_X509_pop_free(x509s, X509_free);
        if (ok < 0) ossl_raise(ePKCS7Error, "PKCS7_verify");
        msg = ERR_reason_error_string(ERR_peek_error());
        ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
        ossl_clear_error();
        data = ossl_membio2str(out);
        ossl_pkcs7_set_data(self, data);

        return (ok == 1) ? Qtrue : Qfalse;
    }