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