Skip to content

Commit 45d19cb

Browse files
committed
WIP implementation of PKCS7::SignerInfo#add_signed_attribute
1 parent 879c139 commit 45d19cb

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
@@ -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

Comments
 (0)