Fix -I, reported by Bernard Leak <bernard@brenda-arkle.demon.co.uk>.
[libtasn1.git] / src / CertificateExample.c
blobeb2120b836b7d974a91fbaadad107a7bc90bc9b1
1 /*
2 * Copyright (C) 2000,2001 Fabio Fiorina
4 * This file is part of LIBTASN1.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA
23 /*****************************************************/
24 /* File: CertificateExample.c */
25 /* Description: An example on how to use the ASN1 */
26 /* parser with the Certificate.txt file */
27 /*****************************************************/
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include "libtasn1.h"
35 char *
36 my_ltostr(long v,char *str)
38 long d,r;
39 char temp[20];
40 int count,k,start;
42 if(v<0){
43 str[0]='-';
44 start=1;
45 v=-v;
47 else start=0;
49 count=0;
50 do{
51 d=v/10;
52 r=v-d*10;
53 temp[start+count]='0'+(char)r;
54 count++;
55 v=d;
56 }while(v);
58 for(k=0;k<count;k++) str[k+start]=temp[start+count-k-1];
59 str[count+start]=0;
60 return str;
63 /******************************************************/
64 /* Function : get_name_type */
65 /* Description: analyze a structure of type Name */
66 /* Parameters: */
67 /* char *root: the structure identifier */
68 /* char *answer: the string with elements like: */
69 /* "C=US O=gov" */
70 /******************************************************/
71 void
72 get_Name_type(node_asn *cert_def,node_asn *cert,char *root, char *answer)
74 int k,k2,result,len;
75 char name[128],str[1024],str2[1024],name2[128],counter[5],name3[128];
76 ASN1_TYPE value=ASN1_TYPE_EMPTY;
77 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
79 answer[0]=0;
80 k=1;
81 do{
82 strcpy(name,root);
83 strcat(name,".rdnSequence.?");
84 my_ltostr(k,counter);
85 strcat(name,counter);
86 len = sizeof(str) - 1;
87 result=asn1_read_value(cert,name,str,&len);
88 if(result==ASN1_ELEMENT_NOT_FOUND) break;
89 k2=1;
90 do{
91 strcpy(name2,name);
92 strcat(name2,".?");
93 my_ltostr(k2,counter);
94 strcat(name2,counter);
95 len = sizeof(str) - 1;
96 result=asn1_read_value(cert,name2,str,&len);
97 if(result==ASN1_ELEMENT_NOT_FOUND) break;
98 strcpy(name3,name2);
99 strcat(name3,".type");
100 len = sizeof(str) - 1;
101 result=asn1_read_value(cert,name3,str,&len);
102 strcpy(name3,name2);
103 strcat(name3,".value");
104 if(result==ASN1_SUCCESS){
105 len = sizeof(str2) - 1;
106 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",
107 str2,&len);
108 if(!strcmp(str,str2)){
109 asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName",
110 &value);
111 len = sizeof(str) - 1;
112 asn1_read_value(cert,name3,str,&len);
113 asn1_der_decoding(&value,str,len,errorDescription);
114 len = sizeof(str) - 1;
115 asn1_read_value(value,"",str,&len); /* CHOICE */
116 strcpy(name3,str);
117 len = sizeof(str) - 1;
118 asn1_read_value(value,name3,str,&len);
119 str[len]=0;
120 strcat(answer," C=");
121 strcat(answer,str);
122 asn1_delete_structure(&value);
124 else{
125 len = sizeof(str2) - 1;
126 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName"
127 ,str2,&len);
128 if(!strcmp(str,str2)){
129 asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName"
130 ,&value);
131 len = sizeof(str) - 1;
132 asn1_read_value(cert,name3,str,&len);
133 asn1_der_decoding(&value,str,len,errorDescription);
134 len = sizeof(str) - 1;
135 asn1_read_value(value,"",str,&len); /* CHOICE */
136 strcpy(name3,str);
137 len = sizeof(str) - 1;
138 asn1_read_value(value,name3,str,&len);
139 str[len]=0;
140 strcat(answer," O=");
141 strcat(answer,str);
142 asn1_delete_structure(&value);
144 else{
145 len = sizeof(str2) - 1;
146 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",str2,&len);
147 if(!strcmp(str,str2)){
148 asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
149 len = sizeof(str) - 1;
150 asn1_read_value(cert,name3,str,&len);
151 asn1_der_decoding(&value,str,len,errorDescription);
152 len = sizeof(str) - 1;
153 asn1_read_value(value,"",str,&len); /* CHOICE */
154 strcpy(name3,str);
155 len = sizeof(str) - 1;
156 asn1_read_value(value,name3,str,&len);
157 str[len]=0;
158 strcat(answer," OU=");
159 strcat(answer,str);
160 asn1_delete_structure(&value);
165 k2++;
166 }while(1);
167 k++;
168 }while(1);
172 /******************************************************/
173 /* Function : create_certificate */
174 /* Description: creates a certificate named */
175 /* "certificate1". Values are the same */
176 /* as in rfc2459 Appendix D.1 */
177 /* Parameters: */
178 /* unsigned char *der: contains the der encoding */
179 /* int *der_len: number of bytes of der string */
180 /******************************************************/
181 void
182 create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
184 int result,k,len;
185 unsigned char str[1024],*str2;
186 ASN1_TYPE cert1=ASN1_TYPE_EMPTY;
187 ASN1_TYPE value=ASN1_TYPE_EMPTY;
188 ASN1_TYPE param=ASN1_TYPE_EMPTY;
189 ASN1_TYPE constr=ASN1_TYPE_EMPTY;
190 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
191 int max_len;
193 max_len=*der_len;
195 result=asn1_create_element(cert_def,"PKIX1Implicit88.Certificate",&cert1);
197 /* Use the next 3 lines to visit the empty certificate */
198 /* printf("-----------------\n");
199 asn1_visit_tree(cert1,"");
200 printf("-----------------\n"); */
202 /* version: v3(2) */
203 result=asn1_write_value(cert1,"tbsCertificate.version","v3",0);
205 /* serialNumber: 17 */
206 result=asn1_write_value(cert1,"tbsCertificate.serialNumber","17",0);
208 /* signature: dsa-with-sha1 */
209 len = sizeof(str) - 1;
210 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
211 result=asn1_write_value(cert1,"tbsCertificate.signature.algorithm",
212 str,1);
214 result=asn1_write_value(cert1,"tbsCertificate.signature.parameters",
215 NULL,0);
218 /* issuer: Country="US" Organization="gov" OrganizationUnit="nist" */
219 result=asn1_write_value(cert1,"tbsCertificate.issuer","rdnSequence",12);
221 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence","NEW",1);
222 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
223 /* C */
224 len = sizeof(str) - 1;
225 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
226 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
227 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName",
228 &value);
229 result=asn1_write_value(value,"","US",2);
230 *der_len = max_len;
231 result=asn1_der_coding(value,"",der,der_len,errorDescription);
232 asn1_delete_structure(&value);
233 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
236 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence","NEW",1);
237 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
238 /* O */
239 len = sizeof(str) - 1;
240 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
241 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
242 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName",
243 &value);
244 result=asn1_write_value(value,"","printableString",1);
245 result=asn1_write_value(value,"printableString","gov",3);
246 *der_len = max_len;
247 result=asn1_der_coding(value,"",der,der_len,errorDescription);
248 asn1_delete_structure(&value);
249 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
252 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence","NEW",1);
253 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
255 /* OU */
256 len = sizeof(str) - 1;
257 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
258 str,&len);
259 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
260 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
261 result=asn1_write_value(value,"","printableString",1);
262 result=asn1_write_value(value,"printableString","nist",4);
263 *der_len = max_len;
264 result=asn1_der_coding(value,"",der,der_len,errorDescription);
265 asn1_delete_structure(&value);
266 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
269 /* validity */
270 result=asn1_write_value(cert1,"tbsCertificate.validity.notBefore","utcTime",1);
271 result=asn1_write_value(cert1,"tbsCertificate.validity.notBefore.utcTime","970630000000Z",1);
273 result=asn1_write_value(cert1,"tbsCertificate.validity.notAfter","utcTime",1);
274 result=asn1_write_value(cert1,"tbsCertificate.validity.notAfter.utcTime","971231000000Z",1);
278 /* subject: Country="US" Organization="gov" OrganizationUnit="nist" */
279 result=asn1_write_value(cert1,"tbsCertificate.subject","rdnSequence",1);
281 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence","NEW",1);
282 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST","NEW",1);
283 /* C */
284 len = sizeof(str) - 1;
285 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
286 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
287 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName",
288 &value);
289 result=asn1_write_value(value,"","US",2);
290 *der_len = max_len;
291 result=asn1_der_coding(value,"",der,der_len,errorDescription);
292 asn1_delete_structure(&value);
293 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
296 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence","NEW",4);
297 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
298 /* O */
299 len = sizeof(str) - 1;
300 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
301 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
302 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName",
303 &value);
304 result=asn1_write_value(value,"","printableString",1);
305 result=asn1_write_value(value,"printableString","gov",3);
306 *der_len = max_len;
307 result=asn1_der_coding(value,"",der,der_len,errorDescription);
308 asn1_delete_structure(&value);
309 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
312 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence","NEW",4);
313 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
314 /* OU */
315 len = sizeof(str) - 1;
316 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
317 str,&len);
318 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
319 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
320 result=asn1_write_value(value,"","printableString",1);
321 result=asn1_write_value(value,"printableString","nist",4);
322 *der_len = max_len;
323 result=asn1_der_coding(value,"",der,der_len,errorDescription);
324 asn1_delete_structure(&value);
325 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
328 /* subjectPublicKeyInfo: dsa with parameters=Dss-Parms */
329 len = sizeof(str) - 1;
330 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa",str,&len);
331 result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm",str,1);
332 result=asn1_create_element(cert_def,"PKIX1Implicit88.Dss-Parms",&param);
333 str2="\xd4\x38"; /* only an example */
334 result=asn1_write_value(param,"p",str2,128);
335 str2="\xd4\x38"; /* only an example */
336 result=asn1_write_value(param,"q",str2,20);
337 str2="\xd4\x38"; /* only an example */
338 result=asn1_write_value(param,"g",str2,128);
339 *der_len = max_len;
340 result=asn1_der_coding(param,"",der,der_len,errorDescription);
341 asn1_delete_structure(&param);
342 result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",der,*der_len);
345 /* subjectPublicKey */
346 str2="\x02\x81"; /* only an example */
347 result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",str2,1048);
349 result=asn1_write_value(cert1,"tbsCertificate.issuerUniqueID",NULL,0); /* NO OPTION */
350 result=asn1_write_value(cert1,"tbsCertificate.subjectUniqueID",NULL,0); /* NO OPTION */
352 /* extensions */
353 result=asn1_write_value(cert1,"tbsCertificate.extensions","NEW",1);
354 len = sizeof(str) - 1;
355 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-basicConstraints",
356 str,&len);
357 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnID",str,1); /* basicConstraints */
358 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.critical","TRUE",1);
359 result=asn1_create_element(cert_def,"PKIX1Implicit88.BasicConstraints",&constr);
360 result=asn1_write_value(constr,"cA","TRUE",1);
361 result=asn1_write_value(constr,"pathLenConstraint",NULL,0);
362 *der_len = max_len;
363 result=asn1_der_coding(constr,"",der,der_len,errorDescription);
364 result=asn1_delete_structure(&constr);
365 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnValue",der,*der_len);
368 result=asn1_write_value(cert1,"tbsCertificate.extensions","NEW",1);
369 len = sizeof(str) - 1;
370 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-subjectKeyIdentifier",
371 str,&len);
372 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnID",str,1); /* subjectKeyIdentifier */
373 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.critical","FALSE",1);
374 str2="\x04\x14\xe7\x26\xc5"; /* only an example */
375 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnValue",str2,22);
378 /* signatureAlgorithm: dsa-with-sha */
379 len = sizeof(str) - 1;
380 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
381 result=asn1_write_value(cert1,"signatureAlgorithm.algorithm",str,1);
382 result=asn1_write_value(cert1,"signatureAlgorithm.parameters",NULL,0); /* NO OPTION */
385 /* signature */
386 *der_len = max_len;
387 result=asn1_der_coding(cert1,"tbsCertificate",der,der_len
388 ,errorDescription);
389 if(result!=ASN1_SUCCESS){
390 printf("\n'tbsCertificate' encoding creation: ERROR\n");
392 /* add the lines for the signature on der[0]..der[der_len-1]: result in str2 */
393 result=asn1_write_value(cert1,"signature",str2,368); /* dsa-with-sha */
396 /* Use the next 3 lines to visit the certificate */
397 /* printf("-----------------\n");
398 asn1_visit_tree(cert1,"");
399 printf("-----------------\n"); */
401 *der_len = max_len;
402 result=asn1_der_coding(cert1,"",der,der_len,errorDescription);
403 if(result!=ASN1_SUCCESS){
404 printf("\n'certificate' encoding creation: ERROR\n");
405 return;
408 /* Print the 'Certificate1' DER encoding */
409 printf("-----------------\nCertificate Encoding:\nNumber of bytes=%i\n",*der_len);
410 for(k=0;k<*der_len;k++) printf("%02x ",der[k]);
411 printf("\n-----------------\n");
413 /* Clear the "certificate1" structure */
414 asn1_delete_structure(&cert1);
419 /******************************************************/
420 /* Function : get_certificate */
421 /* Description: creates a certificate named */
422 /* "certificate2" from a der encoding */
423 /* string */
424 /* Parameters: */
425 /* unsigned char *der: the encoding string */
426 /* int der_len: number of bytes of der string */
427 /******************************************************/
428 void
429 get_certificate(node_asn *cert_def,unsigned char *der,int der_len)
431 int result,len,start,end;
432 unsigned char str[1024],str2[1024];
433 ASN1_TYPE cert2=ASN1_TYPE_EMPTY;
434 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
436 asn1_create_element(cert_def,"PKIX1Implicit88.Certificate",&cert2);
438 result=asn1_der_decoding(&cert2,der,der_len,errorDescription);
440 if(result!=ASN1_SUCCESS){
441 printf("Problems with DER encoding\n");
442 return;
446 /* issuer */
447 get_Name_type(cert_def,cert2,"tbsCertificate.issuer",str);
448 printf("certificate:\nissuer :%s\n",str);
449 /* subject */
450 get_Name_type(cert_def,cert2,"tbsCertificate.subject",str);
451 printf("subject:%s\n",str);
454 /* Verify sign */
455 len = sizeof(str) - 1;
456 result=asn1_read_value(cert2,"signatureAlgorithm.algorithm"
457 ,str,&len);
459 len = sizeof(str2) - 1;
460 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str2,&len);
461 if(!strcmp(str,str2)){ /* dsa-with-sha */
463 result=asn1_der_decoding_startEnd(cert2,der,der_len,
464 "tbsCertificate",&start,&end);
466 /* add the lines to calculate the sha on der[start]..der[end] */
468 len = sizeof(str) - 1;
469 result=asn1_read_value(cert2,"signature",str,&len);
471 /* compare the previous value to signature ( with issuer public key) */
474 /* Use the next 3 lines to visit the certificate */
475 /* printf("-----------------\n");
476 asn1_visit_tree(cert2,"");
477 printf("-----------------\n"); */
480 /* Clear the "certificate2" structure */
481 asn1_delete_structure(&cert2);
484 #include "pkix_asn1_tab.c"
486 /********************************************************/
487 /* Function : main */
488 /* Description: reads the certificate description. */
489 /* Creates a certificate and calculate */
490 /* the der encoding. After that creates */
491 /* another certificate from der string */
492 /********************************************************/
494 main(int argc,char *argv[])
496 int result,der_len;
497 unsigned char der[1024];
498 ASN1_TYPE PKIX1Implicit88=ASN1_TYPE_EMPTY;
499 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
501 if(1)
502 result=asn1_array2tree(pkix_asn1_tab,&PKIX1Implicit88,errorDescription);
503 else
504 result=asn1_parser2tree("pkix.asn",&PKIX1Implicit88,errorDescription);
506 if(result != ASN1_SUCCESS){
507 libtasn1_perror(result);
508 printf("%s",errorDescription);
509 exit(1);
513 /* Use the following 3 lines to visit the PKIX1Implicit structures */
514 /* printf("-----------------\n");
515 asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88");
516 printf("-----------------\n"); */
518 der_len=1024;
519 create_certificate(PKIX1Implicit88,der,&der_len);
521 get_certificate(PKIX1Implicit88,der,der_len);
523 /* Clear the "PKIX1Implicit88" structures */
524 asn1_delete_structure(&PKIX1Implicit88);
526 return 0;