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