Version 1.3.
[libtasn1.git] / examples / CertificateExample.c
blobf4b047e2e0e97ad5d2b63cc5da97a125008ec84c
1 /*
2 * Copyright (C) 2006, 2007, 2008 Free Software Foundation
3 * Copyright (C) 2000,2001 Fabio Fiorina
5 * This file is part of LIBTASN1.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /*****************************************************/
23 /* File: CertificateExample.c */
24 /* Description: An example on how to use the ASN1 */
25 /* parser with the Certificate.txt file */
26 /*****************************************************/
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include "libtasn1.h"
34 static char *
35 my_ltostr(long v,char *str)
37 long d,r;
38 char temp[20];
39 int count,k,start;
41 if(v<0){
42 str[0]='-';
43 start=1;
44 v=-v;
46 else start=0;
48 count=0;
49 do{
50 d=v/10;
51 r=v-d*10;
52 temp[start+count]='0'+(char)r;
53 count++;
54 v=d;
55 }while(v);
57 for(k=0;k<count;k++) str[k+start]=temp[start+count-k-1];
58 str[count+start]=0;
59 return str;
62 /******************************************************/
63 /* Function : get_name_type */
64 /* Description: analyze a structure of type Name */
65 /* Parameters: */
66 /* char *root: the structure identifier */
67 /* char *answer: the string with elements like: */
68 /* "C=US O=gov" */
69 /******************************************************/
70 static void
71 get_Name_type(node_asn *cert_def,node_asn *cert,char *root, char *answer)
73 int k,k2,result,len;
74 char name[128],str[1024],str2[1024],name2[128],counter[5],name3[128];
75 ASN1_TYPE value=ASN1_TYPE_EMPTY;
76 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
78 answer[0]=0;
79 k=1;
80 do{
81 strcpy(name,root);
82 strcat(name,".rdnSequence.?");
83 my_ltostr(k,counter);
84 strcat(name,counter);
85 len = sizeof(str) - 1;
86 result=asn1_read_value(cert,name,str,&len);
87 if(result==ASN1_ELEMENT_NOT_FOUND) break;
88 k2=1;
89 do{
90 strcpy(name2,name);
91 strcat(name2,".?");
92 my_ltostr(k2,counter);
93 strcat(name2,counter);
94 len = sizeof(str) - 1;
95 result=asn1_read_value(cert,name2,str,&len);
96 if(result==ASN1_ELEMENT_NOT_FOUND) break;
97 strcpy(name3,name2);
98 strcat(name3,".type");
99 len = sizeof(str) - 1;
100 result=asn1_read_value(cert,name3,str,&len);
101 strcpy(name3,name2);
102 strcat(name3,".value");
103 if(result==ASN1_SUCCESS){
104 len = sizeof(str2) - 1;
105 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",
106 str2,&len);
107 if(!strcmp(str,str2)){
108 asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName",
109 &value);
110 len = sizeof(str) - 1;
111 asn1_read_value(cert,name3,str,&len);
112 asn1_der_decoding(&value,str,len,errorDescription);
113 len = sizeof(str) - 1;
114 asn1_read_value(value,"",str,&len); /* CHOICE */
115 strcpy(name3,str);
116 len = sizeof(str) - 1;
117 asn1_read_value(value,name3,str,&len);
118 str[len]=0;
119 strcat(answer," C=");
120 strcat(answer,str);
121 asn1_delete_structure(&value);
123 else{
124 len = sizeof(str2) - 1;
125 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName"
126 ,str2,&len);
127 if(!strcmp(str,str2)){
128 asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName"
129 ,&value);
130 len = sizeof(str) - 1;
131 asn1_read_value(cert,name3,str,&len);
132 asn1_der_decoding(&value,str,len,errorDescription);
133 len = sizeof(str) - 1;
134 asn1_read_value(value,"",str,&len); /* CHOICE */
135 strcpy(name3,str);
136 len = sizeof(str) - 1;
137 asn1_read_value(value,name3,str,&len);
138 str[len]=0;
139 strcat(answer," O=");
140 strcat(answer,str);
141 asn1_delete_structure(&value);
143 else{
144 len = sizeof(str2) - 1;
145 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",str2,&len);
146 if(!strcmp(str,str2)){
147 asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
148 len = sizeof(str) - 1;
149 asn1_read_value(cert,name3,str,&len);
150 asn1_der_decoding(&value,str,len,errorDescription);
151 len = sizeof(str) - 1;
152 asn1_read_value(value,"",str,&len); /* CHOICE */
153 strcpy(name3,str);
154 len = sizeof(str) - 1;
155 asn1_read_value(value,name3,str,&len);
156 str[len]=0;
157 strcat(answer," OU=");
158 strcat(answer,str);
159 asn1_delete_structure(&value);
164 k2++;
165 }while(1);
166 k++;
167 }while(1);
171 /******************************************************/
172 /* Function : create_certificate */
173 /* Description: creates a certificate named */
174 /* "certificate1". Values are the same */
175 /* as in rfc2459 Appendix D.1 */
176 /* Parameters: */
177 /* unsigned char *der: contains the der encoding */
178 /* int *der_len: number of bytes of der string */
179 /******************************************************/
180 static void
181 create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
183 int result,k,len;
184 unsigned char str[1024],*str2;
185 ASN1_TYPE cert1=ASN1_TYPE_EMPTY;
186 ASN1_TYPE value=ASN1_TYPE_EMPTY;
187 ASN1_TYPE param=ASN1_TYPE_EMPTY;
188 ASN1_TYPE constr=ASN1_TYPE_EMPTY;
189 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
190 int max_len;
192 max_len=*der_len;
194 result=asn1_create_element(cert_def,"PKIX1Implicit88.Certificate",&cert1);
196 /* Use the next 3 lines to visit the empty certificate */
197 /* printf("-----------------\n");
198 asn1_visit_tree(cert1,"");
199 printf("-----------------\n"); */
201 /* version: v3(2) */
202 result=asn1_write_value(cert1,"tbsCertificate.version","v3",0);
204 /* serialNumber: 17 */
205 result=asn1_write_value(cert1,"tbsCertificate.serialNumber","17",0);
207 /* signature: dsa-with-sha1 */
208 len = sizeof(str) - 1;
209 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
210 result=asn1_write_value(cert1,"tbsCertificate.signature.algorithm",
211 str,1);
213 result=asn1_write_value(cert1,"tbsCertificate.signature.parameters",
214 NULL,0);
217 /* issuer: Country="US" Organization="gov" OrganizationUnit="nist" */
218 result=asn1_write_value(cert1,"tbsCertificate.issuer","rdnSequence",12);
220 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence","NEW",1);
221 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
222 /* C */
223 len = sizeof(str) - 1;
224 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
225 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
226 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName",
227 &value);
228 result=asn1_write_value(value,"","US",2);
229 *der_len = max_len;
230 result=asn1_der_coding(value,"",der,der_len,errorDescription);
231 asn1_delete_structure(&value);
232 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
235 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence","NEW",1);
236 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
237 /* O */
238 len = sizeof(str) - 1;
239 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
240 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
241 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName",
242 &value);
243 result=asn1_write_value(value,"","printableString",1);
244 result=asn1_write_value(value,"printableString","gov",3);
245 *der_len = max_len;
246 result=asn1_der_coding(value,"",der,der_len,errorDescription);
247 asn1_delete_structure(&value);
248 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
251 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence","NEW",1);
252 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
254 /* OU */
255 len = sizeof(str) - 1;
256 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
257 str,&len);
258 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
259 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
260 result=asn1_write_value(value,"","printableString",1);
261 result=asn1_write_value(value,"printableString","nist",4);
262 *der_len = max_len;
263 result=asn1_der_coding(value,"",der,der_len,errorDescription);
264 asn1_delete_structure(&value);
265 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
268 /* validity */
269 result=asn1_write_value(cert1,"tbsCertificate.validity.notBefore","utcTime",1);
270 result=asn1_write_value(cert1,"tbsCertificate.validity.notBefore.utcTime","970630000000Z",1);
272 result=asn1_write_value(cert1,"tbsCertificate.validity.notAfter","utcTime",1);
273 result=asn1_write_value(cert1,"tbsCertificate.validity.notAfter.utcTime","971231000000Z",1);
277 /* subject: Country="US" Organization="gov" OrganizationUnit="nist" */
278 result=asn1_write_value(cert1,"tbsCertificate.subject","rdnSequence",1);
280 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence","NEW",1);
281 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST","NEW",1);
282 /* C */
283 len = sizeof(str) - 1;
284 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
285 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
286 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName",
287 &value);
288 result=asn1_write_value(value,"","US",2);
289 *der_len = max_len;
290 result=asn1_der_coding(value,"",der,der_len,errorDescription);
291 asn1_delete_structure(&value);
292 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
295 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence","NEW",4);
296 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
297 /* O */
298 len = sizeof(str) - 1;
299 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
300 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
301 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName",
302 &value);
303 result=asn1_write_value(value,"","printableString",1);
304 result=asn1_write_value(value,"printableString","gov",3);
305 *der_len = max_len;
306 result=asn1_der_coding(value,"",der,der_len,errorDescription);
307 asn1_delete_structure(&value);
308 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
311 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence","NEW",4);
312 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
313 /* OU */
314 len = sizeof(str) - 1;
315 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
316 str,&len);
317 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
318 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
319 result=asn1_write_value(value,"","printableString",1);
320 result=asn1_write_value(value,"printableString","nist",4);
321 *der_len = max_len;
322 result=asn1_der_coding(value,"",der,der_len,errorDescription);
323 asn1_delete_structure(&value);
324 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
327 /* subjectPublicKeyInfo: dsa with parameters=Dss-Parms */
328 len = sizeof(str) - 1;
329 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa",str,&len);
330 result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm",str,1);
331 result=asn1_create_element(cert_def,"PKIX1Implicit88.Dss-Parms",&param);
332 str2="\xd4\x38"; /* only an example */
333 result=asn1_write_value(param,"p",str2,128);
334 str2="\xd4\x38"; /* only an example */
335 result=asn1_write_value(param,"q",str2,20);
336 str2="\xd4\x38"; /* only an example */
337 result=asn1_write_value(param,"g",str2,128);
338 *der_len = max_len;
339 result=asn1_der_coding(param,"",der,der_len,errorDescription);
340 asn1_delete_structure(&param);
341 result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",der,*der_len);
344 /* subjectPublicKey */
345 str2="\x02\x81"; /* only an example */
346 result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",str2,1048);
348 result=asn1_write_value(cert1,"tbsCertificate.issuerUniqueID",NULL,0); /* NO OPTION */
349 result=asn1_write_value(cert1,"tbsCertificate.subjectUniqueID",NULL,0); /* NO OPTION */
351 /* extensions */
352 result=asn1_write_value(cert1,"tbsCertificate.extensions","NEW",1);
353 len = sizeof(str) - 1;
354 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-basicConstraints",
355 str,&len);
356 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnID",str,1); /* basicConstraints */
357 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.critical","TRUE",1);
358 result=asn1_create_element(cert_def,"PKIX1Implicit88.BasicConstraints",&constr);
359 result=asn1_write_value(constr,"cA","TRUE",1);
360 result=asn1_write_value(constr,"pathLenConstraint",NULL,0);
361 *der_len = max_len;
362 result=asn1_der_coding(constr,"",der,der_len,errorDescription);
363 result=asn1_delete_structure(&constr);
364 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnValue",der,*der_len);
367 result=asn1_write_value(cert1,"tbsCertificate.extensions","NEW",1);
368 len = sizeof(str) - 1;
369 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-subjectKeyIdentifier",
370 str,&len);
371 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnID",str,1); /* subjectKeyIdentifier */
372 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.critical","FALSE",1);
373 str2="\x04\x14\xe7\x26\xc5"; /* only an example */
374 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnValue",str2,22);
377 /* signatureAlgorithm: dsa-with-sha */
378 len = sizeof(str) - 1;
379 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
380 result=asn1_write_value(cert1,"signatureAlgorithm.algorithm",str,1);
381 result=asn1_write_value(cert1,"signatureAlgorithm.parameters",NULL,0); /* NO OPTION */
384 /* signature */
385 *der_len = max_len;
386 result=asn1_der_coding(cert1,"tbsCertificate",der,der_len
387 ,errorDescription);
388 if(result!=ASN1_SUCCESS){
389 printf("\n'tbsCertificate' encoding creation: ERROR\n");
391 /* add the lines for the signature on der[0]..der[der_len-1]: result in str2 */
392 result=asn1_write_value(cert1,"signature",str2,368); /* dsa-with-sha */
395 /* Use the next 3 lines to visit the certificate */
396 /* printf("-----------------\n");
397 asn1_visit_tree(cert1,"");
398 printf("-----------------\n"); */
400 *der_len = max_len;
401 result=asn1_der_coding(cert1,"",der,der_len,errorDescription);
402 if(result!=ASN1_SUCCESS){
403 printf("\n'certificate' encoding creation: ERROR\n");
404 return;
407 /* Print the 'Certificate1' DER encoding */
408 printf("-----------------\nCertificate Encoding:\nNumber of bytes=%i\n",*der_len);
409 for(k=0;k<*der_len;k++) printf("%02x ",der[k]);
410 printf("\n-----------------\n");
412 /* Clear the "certificate1" structure */
413 asn1_delete_structure(&cert1);
418 /******************************************************/
419 /* Function : get_certificate */
420 /* Description: creates a certificate named */
421 /* "certificate2" from a der encoding */
422 /* string */
423 /* Parameters: */
424 /* unsigned char *der: the encoding string */
425 /* int der_len: number of bytes of der string */
426 /******************************************************/
427 static void
428 get_certificate(node_asn *cert_def,unsigned char *der,int der_len)
430 int result,len,start,end;
431 unsigned char str[1024],str2[1024];
432 ASN1_TYPE cert2=ASN1_TYPE_EMPTY;
433 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
435 asn1_create_element(cert_def,"PKIX1Implicit88.Certificate",&cert2);
437 result=asn1_der_decoding(&cert2,der,der_len,errorDescription);
439 if(result!=ASN1_SUCCESS){
440 printf("Problems with DER encoding\n");
441 return;
445 /* issuer */
446 get_Name_type(cert_def,cert2,"tbsCertificate.issuer",str);
447 printf("certificate:\nissuer :%s\n",str);
448 /* subject */
449 get_Name_type(cert_def,cert2,"tbsCertificate.subject",str);
450 printf("subject:%s\n",str);
453 /* Verify sign */
454 len = sizeof(str) - 1;
455 result=asn1_read_value(cert2,"signatureAlgorithm.algorithm"
456 ,str,&len);
458 len = sizeof(str2) - 1;
459 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str2,&len);
460 if(!strcmp(str,str2)){ /* dsa-with-sha */
462 result=asn1_der_decoding_startEnd(cert2,der,der_len,
463 "tbsCertificate",&start,&end);
465 /* add the lines to calculate the sha on der[start]..der[end] */
467 len = sizeof(str) - 1;
468 result=asn1_read_value(cert2,"signature",str,&len);
470 /* compare the previous value to signature ( with issuer public key) */
473 /* Use the next 3 lines to visit the certificate */
474 /* printf("-----------------\n");
475 asn1_visit_tree(cert2,"");
476 printf("-----------------\n"); */
479 /* Clear the "certificate2" structure */
480 asn1_delete_structure(&cert2);
483 extern const ASN1_ARRAY_TYPE pkix_asn1_tab[];
485 /********************************************************/
486 /* Function : main */
487 /* Description: reads the certificate description. */
488 /* Creates a certificate and calculate */
489 /* the der encoding. After that creates */
490 /* another certificate from der string */
491 /********************************************************/
493 main(int argc,char *argv[])
495 int result,der_len;
496 unsigned char der[1024];
497 ASN1_TYPE PKIX1Implicit88=ASN1_TYPE_EMPTY;
498 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
500 if(1)
501 result=asn1_array2tree(pkix_asn1_tab,&PKIX1Implicit88,errorDescription);
502 else
503 result=asn1_parser2tree("pkix.asn",&PKIX1Implicit88,errorDescription);
505 if(result != ASN1_SUCCESS){
506 libtasn1_perror(result);
507 printf("%s",errorDescription);
508 exit(1);
512 /* Use the following 3 lines to visit the PKIX1Implicit structures */
513 /* printf("-----------------\n");
514 asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88");
515 printf("-----------------\n"); */
517 der_len=1024;
518 create_certificate(PKIX1Implicit88,der,&der_len);
520 get_certificate(PKIX1Implicit88,der,der_len);
522 /* Clear the "PKIX1Implicit88" structures */
523 asn1_delete_structure(&PKIX1Implicit88);
525 return 0;