@@ -987,6 +987,89 @@ ossl_pkcs7si_get_signed_time(VALUE self)
987
987
return Qnil ;
988
988
}
989
989
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
+
990
1073
/*
991
1074
* RECIPIENT INFO
992
1075
*/
@@ -1105,6 +1188,7 @@ Init_ossl_pkcs7(void)
1105
1188
rb_define_method (cPKCS7Signer , "issuer" , ossl_pkcs7si_get_issuer , 0 );
1106
1189
rb_define_method (cPKCS7Signer , "serial" , ossl_pkcs7si_get_serial ,0 );
1107
1190
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 );
1108
1192
1109
1193
cPKCS7Recipient = rb_define_class_under (cPKCS7 ,"RecipientInfo" ,rb_cObject );
1110
1194
rb_define_alloc_func (cPKCS7Recipient , ossl_pkcs7ri_alloc );
0 commit comments