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