1*0Sstevel@tonic-gate #include <stdio.h> 2*0Sstevel@tonic-gate #include <stdlib.h> 3*0Sstevel@tonic-gate #include <string.h> 4*0Sstevel@tonic-gate #include <openssl/pkcs7.h> 5*0Sstevel@tonic-gate #include <openssl/asn1_mac.h> 6*0Sstevel@tonic-gate #include <openssl/x509.h> 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate int add_signed_time(PKCS7_SIGNER_INFO *si) 9*0Sstevel@tonic-gate { 10*0Sstevel@tonic-gate ASN1_UTCTIME *sign_time; 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gate /* The last parameter is the amount to add/subtract from the current 13*0Sstevel@tonic-gate * time (in seconds) */ 14*0Sstevel@tonic-gate sign_time=X509_gmtime_adj(NULL,0); 15*0Sstevel@tonic-gate PKCS7_add_signed_attribute(si,NID_pkcs9_signingTime, 16*0Sstevel@tonic-gate V_ASN1_UTCTIME,(char *)sign_time); 17*0Sstevel@tonic-gate return(1); 18*0Sstevel@tonic-gate } 19*0Sstevel@tonic-gate 20*0Sstevel@tonic-gate ASN1_UTCTIME *get_signed_time(PKCS7_SIGNER_INFO *si) 21*0Sstevel@tonic-gate { 22*0Sstevel@tonic-gate ASN1_TYPE *so; 23*0Sstevel@tonic-gate 24*0Sstevel@tonic-gate so=PKCS7_get_signed_attribute(si,NID_pkcs9_signingTime); 25*0Sstevel@tonic-gate if (so->type == V_ASN1_UTCTIME) 26*0Sstevel@tonic-gate return so->value.utctime; 27*0Sstevel@tonic-gate return NULL; 28*0Sstevel@tonic-gate } 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate static int signed_string_nid= -1; 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate void add_signed_string(PKCS7_SIGNER_INFO *si, char *str) 33*0Sstevel@tonic-gate { 34*0Sstevel@tonic-gate ASN1_OCTET_STRING *os; 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate /* To a an object of OID 1.2.3.4.5, which is an octet string */ 37*0Sstevel@tonic-gate if (signed_string_nid == -1) 38*0Sstevel@tonic-gate signed_string_nid= 39*0Sstevel@tonic-gate OBJ_create("1.2.3.4.5","OID_example","Our example OID"); 40*0Sstevel@tonic-gate os=ASN1_OCTET_STRING_new(); 41*0Sstevel@tonic-gate ASN1_OCTET_STRING_set(os,(unsigned char*)str,strlen(str)); 42*0Sstevel@tonic-gate /* When we add, we do not free */ 43*0Sstevel@tonic-gate PKCS7_add_signed_attribute(si,signed_string_nid, 44*0Sstevel@tonic-gate V_ASN1_OCTET_STRING,(char *)os); 45*0Sstevel@tonic-gate } 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate int get_signed_string(PKCS7_SIGNER_INFO *si, char *buf, int len) 48*0Sstevel@tonic-gate { 49*0Sstevel@tonic-gate ASN1_TYPE *so; 50*0Sstevel@tonic-gate ASN1_OCTET_STRING *os; 51*0Sstevel@tonic-gate int i; 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate if (signed_string_nid == -1) 54*0Sstevel@tonic-gate signed_string_nid= 55*0Sstevel@tonic-gate OBJ_create("1.2.3.4.5","OID_example","Our example OID"); 56*0Sstevel@tonic-gate /* To retrieve */ 57*0Sstevel@tonic-gate so=PKCS7_get_signed_attribute(si,signed_string_nid); 58*0Sstevel@tonic-gate if (so != NULL) 59*0Sstevel@tonic-gate { 60*0Sstevel@tonic-gate if (so->type == V_ASN1_OCTET_STRING) 61*0Sstevel@tonic-gate { 62*0Sstevel@tonic-gate os=so->value.octet_string; 63*0Sstevel@tonic-gate i=os->length; 64*0Sstevel@tonic-gate if ((i+1) > len) 65*0Sstevel@tonic-gate i=len-1; 66*0Sstevel@tonic-gate memcpy(buf,os->data,i); 67*0Sstevel@tonic-gate return(i); 68*0Sstevel@tonic-gate } 69*0Sstevel@tonic-gate } 70*0Sstevel@tonic-gate return(0); 71*0Sstevel@tonic-gate } 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate static int signed_seq2string_nid= -1; 74*0Sstevel@tonic-gate /* ########################################### */ 75*0Sstevel@tonic-gate int add_signed_seq2string(PKCS7_SIGNER_INFO *si, char *str1, char *str2) 76*0Sstevel@tonic-gate { 77*0Sstevel@tonic-gate /* To add an object of OID 1.9.999, which is a sequence containing 78*0Sstevel@tonic-gate * 2 octet strings */ 79*0Sstevel@tonic-gate unsigned char *p; 80*0Sstevel@tonic-gate ASN1_OCTET_STRING *os1,*os2; 81*0Sstevel@tonic-gate ASN1_STRING *seq; 82*0Sstevel@tonic-gate unsigned char *data; 83*0Sstevel@tonic-gate int i,total; 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate if (signed_seq2string_nid == -1) 86*0Sstevel@tonic-gate signed_seq2string_nid= 87*0Sstevel@tonic-gate OBJ_create("1.9.9999","OID_example","Our example OID"); 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate os1=ASN1_OCTET_STRING_new(); 90*0Sstevel@tonic-gate os2=ASN1_OCTET_STRING_new(); 91*0Sstevel@tonic-gate ASN1_OCTET_STRING_set(os1,(unsigned char*)str1,strlen(str1)); 92*0Sstevel@tonic-gate ASN1_OCTET_STRING_set(os2,(unsigned char*)str1,strlen(str1)); 93*0Sstevel@tonic-gate i =i2d_ASN1_OCTET_STRING(os1,NULL); 94*0Sstevel@tonic-gate i+=i2d_ASN1_OCTET_STRING(os2,NULL); 95*0Sstevel@tonic-gate total=ASN1_object_size(1,i,V_ASN1_SEQUENCE); 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate data=malloc(total); 98*0Sstevel@tonic-gate p=data; 99*0Sstevel@tonic-gate ASN1_put_object(&p,1,i,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); 100*0Sstevel@tonic-gate i2d_ASN1_OCTET_STRING(os1,&p); 101*0Sstevel@tonic-gate i2d_ASN1_OCTET_STRING(os2,&p); 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate seq=ASN1_STRING_new(); 104*0Sstevel@tonic-gate ASN1_STRING_set(seq,data,total); 105*0Sstevel@tonic-gate free(data); 106*0Sstevel@tonic-gate ASN1_OCTET_STRING_free(os1); 107*0Sstevel@tonic-gate ASN1_OCTET_STRING_free(os2); 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate PKCS7_add_signed_attribute(si,signed_seq2string_nid, 110*0Sstevel@tonic-gate V_ASN1_SEQUENCE,(char *)seq); 111*0Sstevel@tonic-gate return(1); 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate /* For this case, I will malloc the return strings */ 115*0Sstevel@tonic-gate int get_signed_seq2string(PKCS7_SIGNER_INFO *si, char **str1, char **str2) 116*0Sstevel@tonic-gate { 117*0Sstevel@tonic-gate ASN1_TYPE *so; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate if (signed_seq2string_nid == -1) 120*0Sstevel@tonic-gate signed_seq2string_nid= 121*0Sstevel@tonic-gate OBJ_create("1.9.9999","OID_example","Our example OID"); 122*0Sstevel@tonic-gate /* To retrieve */ 123*0Sstevel@tonic-gate so=PKCS7_get_signed_attribute(si,signed_seq2string_nid); 124*0Sstevel@tonic-gate if (so && (so->type == V_ASN1_SEQUENCE)) 125*0Sstevel@tonic-gate { 126*0Sstevel@tonic-gate ASN1_CTX c; 127*0Sstevel@tonic-gate ASN1_STRING *s; 128*0Sstevel@tonic-gate long length; 129*0Sstevel@tonic-gate ASN1_OCTET_STRING *os1,*os2; 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate s=so->value.sequence; 132*0Sstevel@tonic-gate c.p=ASN1_STRING_data(s); 133*0Sstevel@tonic-gate c.max=c.p+ASN1_STRING_length(s); 134*0Sstevel@tonic-gate if (!asn1_GetSequence(&c,&length)) goto err; 135*0Sstevel@tonic-gate /* Length is the length of the seqence */ 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate c.q=c.p; 138*0Sstevel@tonic-gate if ((os1=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL) 139*0Sstevel@tonic-gate goto err; 140*0Sstevel@tonic-gate c.slen-=(c.p-c.q); 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate c.q=c.p; 143*0Sstevel@tonic-gate if ((os2=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL) 144*0Sstevel@tonic-gate goto err; 145*0Sstevel@tonic-gate c.slen-=(c.p-c.q); 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate if (!asn1_Finish(&c)) goto err; 148*0Sstevel@tonic-gate *str1=malloc(os1->length+1); 149*0Sstevel@tonic-gate *str2=malloc(os2->length+1); 150*0Sstevel@tonic-gate memcpy(*str1,os1->data,os1->length); 151*0Sstevel@tonic-gate memcpy(*str2,os2->data,os2->length); 152*0Sstevel@tonic-gate (*str1)[os1->length]='\0'; 153*0Sstevel@tonic-gate (*str2)[os2->length]='\0'; 154*0Sstevel@tonic-gate ASN1_OCTET_STRING_free(os1); 155*0Sstevel@tonic-gate ASN1_OCTET_STRING_free(os2); 156*0Sstevel@tonic-gate return(1); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate err: 159*0Sstevel@tonic-gate return(0); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate /* ####################################### 164*0Sstevel@tonic-gate * THE OTHER WAY TO DO THINGS 165*0Sstevel@tonic-gate * ####################################### 166*0Sstevel@tonic-gate */ 167*0Sstevel@tonic-gate X509_ATTRIBUTE *create_time(void) 168*0Sstevel@tonic-gate { 169*0Sstevel@tonic-gate ASN1_UTCTIME *sign_time; 170*0Sstevel@tonic-gate X509_ATTRIBUTE *ret; 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate /* The last parameter is the amount to add/subtract from the current 173*0Sstevel@tonic-gate * time (in seconds) */ 174*0Sstevel@tonic-gate sign_time=X509_gmtime_adj(NULL,0); 175*0Sstevel@tonic-gate ret=X509_ATTRIBUTE_create(NID_pkcs9_signingTime, 176*0Sstevel@tonic-gate V_ASN1_UTCTIME,(char *)sign_time); 177*0Sstevel@tonic-gate return(ret); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate ASN1_UTCTIME *sk_get_time(STACK_OF(X509_ATTRIBUTE) *sk) 181*0Sstevel@tonic-gate { 182*0Sstevel@tonic-gate ASN1_TYPE *so; 183*0Sstevel@tonic-gate PKCS7_SIGNER_INFO si; 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate si.auth_attr=sk; 186*0Sstevel@tonic-gate so=PKCS7_get_signed_attribute(&si,NID_pkcs9_signingTime); 187*0Sstevel@tonic-gate if (so->type == V_ASN1_UTCTIME) 188*0Sstevel@tonic-gate return so->value.utctime; 189*0Sstevel@tonic-gate return NULL; 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate X509_ATTRIBUTE *create_string(char *str) 193*0Sstevel@tonic-gate { 194*0Sstevel@tonic-gate ASN1_OCTET_STRING *os; 195*0Sstevel@tonic-gate X509_ATTRIBUTE *ret; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /* To a an object of OID 1.2.3.4.5, which is an octet string */ 198*0Sstevel@tonic-gate if (signed_string_nid == -1) 199*0Sstevel@tonic-gate signed_string_nid= 200*0Sstevel@tonic-gate OBJ_create("1.2.3.4.5","OID_example","Our example OID"); 201*0Sstevel@tonic-gate os=ASN1_OCTET_STRING_new(); 202*0Sstevel@tonic-gate ASN1_OCTET_STRING_set(os,(unsigned char*)str,strlen(str)); 203*0Sstevel@tonic-gate /* When we add, we do not free */ 204*0Sstevel@tonic-gate ret=X509_ATTRIBUTE_create(signed_string_nid, 205*0Sstevel@tonic-gate V_ASN1_OCTET_STRING,(char *)os); 206*0Sstevel@tonic-gate return(ret); 207*0Sstevel@tonic-gate } 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate int sk_get_string(STACK_OF(X509_ATTRIBUTE) *sk, char *buf, int len) 210*0Sstevel@tonic-gate { 211*0Sstevel@tonic-gate ASN1_TYPE *so; 212*0Sstevel@tonic-gate ASN1_OCTET_STRING *os; 213*0Sstevel@tonic-gate int i; 214*0Sstevel@tonic-gate PKCS7_SIGNER_INFO si; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate si.auth_attr=sk; 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate if (signed_string_nid == -1) 219*0Sstevel@tonic-gate signed_string_nid= 220*0Sstevel@tonic-gate OBJ_create("1.2.3.4.5","OID_example","Our example OID"); 221*0Sstevel@tonic-gate /* To retrieve */ 222*0Sstevel@tonic-gate so=PKCS7_get_signed_attribute(&si,signed_string_nid); 223*0Sstevel@tonic-gate if (so != NULL) 224*0Sstevel@tonic-gate { 225*0Sstevel@tonic-gate if (so->type == V_ASN1_OCTET_STRING) 226*0Sstevel@tonic-gate { 227*0Sstevel@tonic-gate os=so->value.octet_string; 228*0Sstevel@tonic-gate i=os->length; 229*0Sstevel@tonic-gate if ((i+1) > len) 230*0Sstevel@tonic-gate i=len-1; 231*0Sstevel@tonic-gate memcpy(buf,os->data,i); 232*0Sstevel@tonic-gate return(i); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate return(0); 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate X509_ATTRIBUTE *add_seq2string(PKCS7_SIGNER_INFO *si, char *str1, char *str2) 239*0Sstevel@tonic-gate { 240*0Sstevel@tonic-gate /* To add an object of OID 1.9.999, which is a sequence containing 241*0Sstevel@tonic-gate * 2 octet strings */ 242*0Sstevel@tonic-gate unsigned char *p; 243*0Sstevel@tonic-gate ASN1_OCTET_STRING *os1,*os2; 244*0Sstevel@tonic-gate ASN1_STRING *seq; 245*0Sstevel@tonic-gate X509_ATTRIBUTE *ret; 246*0Sstevel@tonic-gate unsigned char *data; 247*0Sstevel@tonic-gate int i,total; 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate if (signed_seq2string_nid == -1) 250*0Sstevel@tonic-gate signed_seq2string_nid= 251*0Sstevel@tonic-gate OBJ_create("1.9.9999","OID_example","Our example OID"); 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate os1=ASN1_OCTET_STRING_new(); 254*0Sstevel@tonic-gate os2=ASN1_OCTET_STRING_new(); 255*0Sstevel@tonic-gate ASN1_OCTET_STRING_set(os1,(unsigned char*)str1,strlen(str1)); 256*0Sstevel@tonic-gate ASN1_OCTET_STRING_set(os2,(unsigned char*)str1,strlen(str1)); 257*0Sstevel@tonic-gate i =i2d_ASN1_OCTET_STRING(os1,NULL); 258*0Sstevel@tonic-gate i+=i2d_ASN1_OCTET_STRING(os2,NULL); 259*0Sstevel@tonic-gate total=ASN1_object_size(1,i,V_ASN1_SEQUENCE); 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate data=malloc(total); 262*0Sstevel@tonic-gate p=data; 263*0Sstevel@tonic-gate ASN1_put_object(&p,1,i,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); 264*0Sstevel@tonic-gate i2d_ASN1_OCTET_STRING(os1,&p); 265*0Sstevel@tonic-gate i2d_ASN1_OCTET_STRING(os2,&p); 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate seq=ASN1_STRING_new(); 268*0Sstevel@tonic-gate ASN1_STRING_set(seq,data,total); 269*0Sstevel@tonic-gate free(data); 270*0Sstevel@tonic-gate ASN1_OCTET_STRING_free(os1); 271*0Sstevel@tonic-gate ASN1_OCTET_STRING_free(os2); 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate ret=X509_ATTRIBUTE_create(signed_seq2string_nid, 274*0Sstevel@tonic-gate V_ASN1_SEQUENCE,(char *)seq); 275*0Sstevel@tonic-gate return(ret); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate /* For this case, I will malloc the return strings */ 279*0Sstevel@tonic-gate int sk_get_seq2string(STACK_OF(X509_ATTRIBUTE) *sk, char **str1, char **str2) 280*0Sstevel@tonic-gate { 281*0Sstevel@tonic-gate ASN1_TYPE *so; 282*0Sstevel@tonic-gate PKCS7_SIGNER_INFO si; 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate if (signed_seq2string_nid == -1) 285*0Sstevel@tonic-gate signed_seq2string_nid= 286*0Sstevel@tonic-gate OBJ_create("1.9.9999","OID_example","Our example OID"); 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate si.auth_attr=sk; 289*0Sstevel@tonic-gate /* To retrieve */ 290*0Sstevel@tonic-gate so=PKCS7_get_signed_attribute(&si,signed_seq2string_nid); 291*0Sstevel@tonic-gate if (so->type == V_ASN1_SEQUENCE) 292*0Sstevel@tonic-gate { 293*0Sstevel@tonic-gate ASN1_CTX c; 294*0Sstevel@tonic-gate ASN1_STRING *s; 295*0Sstevel@tonic-gate long length; 296*0Sstevel@tonic-gate ASN1_OCTET_STRING *os1,*os2; 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate s=so->value.sequence; 299*0Sstevel@tonic-gate c.p=ASN1_STRING_data(s); 300*0Sstevel@tonic-gate c.max=c.p+ASN1_STRING_length(s); 301*0Sstevel@tonic-gate if (!asn1_GetSequence(&c,&length)) goto err; 302*0Sstevel@tonic-gate /* Length is the length of the seqence */ 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate c.q=c.p; 305*0Sstevel@tonic-gate if ((os1=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL) 306*0Sstevel@tonic-gate goto err; 307*0Sstevel@tonic-gate c.slen-=(c.p-c.q); 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate c.q=c.p; 310*0Sstevel@tonic-gate if ((os2=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL) 311*0Sstevel@tonic-gate goto err; 312*0Sstevel@tonic-gate c.slen-=(c.p-c.q); 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate if (!asn1_Finish(&c)) goto err; 315*0Sstevel@tonic-gate *str1=malloc(os1->length+1); 316*0Sstevel@tonic-gate *str2=malloc(os2->length+1); 317*0Sstevel@tonic-gate memcpy(*str1,os1->data,os1->length); 318*0Sstevel@tonic-gate memcpy(*str2,os2->data,os2->length); 319*0Sstevel@tonic-gate (*str1)[os1->length]='\0'; 320*0Sstevel@tonic-gate (*str2)[os2->length]='\0'; 321*0Sstevel@tonic-gate ASN1_OCTET_STRING_free(os1); 322*0Sstevel@tonic-gate ASN1_OCTET_STRING_free(os2); 323*0Sstevel@tonic-gate return(1); 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate err: 326*0Sstevel@tonic-gate return(0); 327*0Sstevel@tonic-gate } 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate 330