@@ -972,6 +972,89 @@ ossl_pkcs7si_get_signed_time(VALUE self)
972972 return Qnil ;
973973}
974974
975+ static VALUE
976+ ossl_pkcs7si_add_signed_attribute (VALUE self , VALUE oid , VALUE value ) {
977+ // PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *si, int nid, int attrtype, void *value)
978+ //
979+ // argument sources:
980+ // si - signer_info from OpenSSL, OpenSSL::PKCS7#signers.first, then rubyobj -> OpenSSL struct
981+ // nid - "numerical id" of OID, how to pivot from OpenSSL::ASN1::ObjectId???
982+ // - nightmare
983+ // - ObjectId has little connection with reality, it's a subclass of Primitive
984+ // attrtype - "and it adds a new ASN.1 ANY object of type attrtype with the given value to the new attribute."
985+ // - what is this?
986+ // value - void PTR, ossl_asn1_get_asn1type has a case statement that produces a correct value
987+
988+ PKCS7_SIGNER_INFO * p7si ;
989+ ASN1_OBJECT * a1obj ;
990+ ASN1_TYPE * value_as_type ; // hacks to use ossl_asn1_get_asn1type's case statement
991+ int nid , tag = 0 ;
992+
993+ GetPKCS7si (self , p7si );
994+
995+ // convert OpenSSL::ASN1::ObjectId to a nid
996+ a1obj = obj_to_asn1obj (ossl_asn1_get_value (oid )); // TODO: error check
997+ nid = OBJ_obj2nid (a1obj ); // TODO: error check (NID_undef)
998+ // it's completely possible someone's using an unknown NID here
999+ // we should raise an informative error if this happens
1000+
1001+ // so about attrtype...
1002+ // i'm assuming this would be something like "OpenSSL::ASN1::Sequence" in Ruby
1003+ // we can determine attrtype from the "value", as essentially the "value" is an attrtype plus value
1004+ // so attrtype is eventually passed into ASN1_TYPE_set
1005+ // ASN1_type_set docs makes explicit references to "V_ASN1_SEQUENCE"/"V_ASN1_BOOLEAN"/"V_ASN1_OTHER"
1006+ // so i'm now pretty convinced i should be able to get this from a1obj
1007+
1008+ // though should we use ossl_asn1_get_tag?
1009+ // ossl_asn1_tag takes VALUE obj -> int
1010+ tag = ossl_asn1_tag (value ); // TODO: error check
1011+
1012+ // how tf do we go from value -> ruby -> openssl somehow? -> "value pointer"
1013+ // maybe this:
1014+ // value = ossl_asn1_get_value(obj); // no, becaue value is a ruby — ossl_asn1_get_asn1type might have something useful
1015+
1016+ // struct asn1_object_st {
1017+ // const char *sn, *ln;
1018+ // int nid;
1019+ // int length;
1020+ // const unsigned char *data;
1021+ // int flags;
1022+ // }
1023+
1024+
1025+ // "void *value" goes PKCS7_signed_attribute -> add_attribute -> X509_ATTRIBUTE_create (x_attrib.c)
1026+ // -> ASN1_TYPE_set(val, atrtype, value)
1027+ // -> a->value.ptr = value;
1028+ // a is an ASN1_TYPE struct (asn1_type_st)
1029+ // include/openssl/asn1.h.in as:
1030+ //
1031+ // struct asn1_type_st {
1032+ // int type;
1033+ // union {
1034+ // char *ptr;
1035+ // // a bunch of other specifically typed attributes like:
1036+ // ASN1_BOOLEAN boolean;
1037+ // ASN1_UNIVERSALSTRING *universalstring;
1038+ // }
1039+ // very unclear on if this matters though?
1040+ //
1041+ // so what do we need? i'm still no closer to actually answering that question
1042+ // i can get an ASN1_OBJECT but that's still not much use to me
1043+ //
1044+ // i can actually get an ASN1_TYPE from ossl_asn1_get_asn1type, which calls
1045+ // ASN1_TYPE_set under the hood via a crazy case statement.
1046+ value_as_type = ossl_asn1_get_asn1type (value );
1047+
1048+ // method sig would be .add_signed_attribute(oid/type, value)
1049+ // where ObjectId is actually a Primitive (???) so how do I handle that?
1050+ // both oid and value are ultimately primitives tbh
1051+ PKCS7_add_signed_attribute (p7si , nid , tag , value_as_type .value );
1052+
1053+ // return the value of the attribute we've just stuck in
1054+ return value ;
1055+ }
1056+
1057+
9751058/*
9761059 * RECIPIENT INFO
9771060 */
@@ -1090,6 +1173,7 @@ Init_ossl_pkcs7(void)
10901173 rb_define_method (cPKCS7Signer , "issuer" , ossl_pkcs7si_get_issuer , 0 );
10911174 rb_define_method (cPKCS7Signer , "serial" , ossl_pkcs7si_get_serial ,0 );
10921175 rb_define_method (cPKCS7Signer ,"signed_time" ,ossl_pkcs7si_get_signed_time ,0 );
1176+ rb_define_method (cPKCS7Signer , "add_signed_attribute" , ossl_pkcs7si_add_signed_attribute , 2 );
10931177
10941178 cPKCS7Recipient = rb_define_class_under (cPKCS7 ,"RecipientInfo" ,rb_cObject );
10951179 rb_define_alloc_func (cPKCS7Recipient , ossl_pkcs7ri_alloc );
0 commit comments