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