Skip to content

Commit 9d0398c

Browse files
committed
WIP implementation of PKCS7::SignerInfo#add_signed_attribute
1 parent 940bffa commit 9d0398c

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

ext/openssl/ossl_pkcs7.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)