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