Fix release.
[libtasn1.git] / src / CertificateExample.c
blobdb72af3c3e14c662ff0e07de075ea1a2cfd2a303
1 /*
2 * Copyright (C) 2006 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
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * 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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA
24 /*****************************************************/
25 /* File: CertificateExample.c */
26 /* Description: An example on how to use the ASN1 */
27 /* parser with the Certificate.txt file */
28 /*****************************************************/
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include "libtasn1.h"
36 char *
37 my_ltostr(long v,char *str)
39 long d,r;
40 char temp[20];
41 int count,k,start;
43 if(v<0){
44 str[0]='-';
45 start=1;
46 v=-v;
48 else start=0;
50 count=0;
51 do{
52 d=v/10;
53 r=v-d*10;
54 temp[start+count]='0'+(char)r;
55 count++;
56 v=d;
57 }while(v);
59 for(k=0;k<count;k++) str[k+start]=temp[start+count-k-1];
60 str[count+start]=0;
61 return str;
64 /******************************************************/
65 /* Function : get_name_type */
66 /* Description: analyze a structure of type Name */
67 /* Parameters: */
68 /* char *root: the structure identifier */
69 /* char *answer: the string with elements like: */
70 /* "C=US O=gov" */
71 /******************************************************/
72 void
73 get_Name_type(node_asn *cert_def,node_asn *cert,char *root, char *answer)
75 int k,k2,result,len;
76 char name[128],str[1024],str2[1024],name2[128],counter[5],name3[128];
77 ASN1_TYPE value=ASN1_TYPE_EMPTY;
78 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
80 answer[0]=0;
81 k=1;
82 do{
83 strcpy(name,root);
84 strcat(name,".rdnSequence.?");
85 my_ltostr(k,counter);
86 strcat(name,counter);
87 len = sizeof(str) - 1;
88 result=asn1_read_value(cert,name,str,&len);
89 if(result==ASN1_ELEMENT_NOT_FOUND) break;
90 k2=1;
91 do{
92 strcpy(name2,name);
93 strcat(name2,".?");
94 my_ltostr(k2,counter);
95 strcat(name2,counter);
96 len = sizeof(str) - 1;
97 result=asn1_read_value(cert,name2,str,&len);
98 if(result==ASN1_ELEMENT_NOT_FOUND) break;
99 strcpy(name3,name2);
100 strcat(name3,".type");
101 len = sizeof(str) - 1;
102 result=asn1_read_value(cert,name3,str,&len);
103 strcpy(name3,name2);
104 strcat(name3,".value");
105 if(result==ASN1_SUCCESS){
106 len = sizeof(str2) - 1;
107 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",
108 str2,&len);
109 if(!strcmp(str,str2)){
110 asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName",
111 &value);
112 len = sizeof(str) - 1;
113 asn1_read_value(cert,name3,str,&len);
114 asn1_der_decoding(&value,str,len,errorDescription);
115 len = sizeof(str) - 1;
116 asn1_read_value(value,"",str,&len); /* CHOICE */
117 strcpy(name3,str);
118 len = sizeof(str) - 1;
119 asn1_read_value(value,name3,str,&len);
120 str[len]=0;
121 strcat(answer," C=");
122 strcat(answer,str);
123 asn1_delete_structure(&value);
125 else{
126 len = sizeof(str2) - 1;
127 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName"
128 ,str2,&len);
129 if(!strcmp(str,str2)){
130 asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName"
131 ,&value);
132 len = sizeof(str) - 1;
133 asn1_read_value(cert,name3,str,&len);
134 asn1_der_decoding(&value,str,len,errorDescription);
135 len = sizeof(str) - 1;
136 asn1_read_value(value,"",str,&len); /* CHOICE */
137 strcpy(name3,str);
138 len = sizeof(str) - 1;
139 asn1_read_value(value,name3,str,&len);
140 str[len]=0;
141 strcat(answer," O=");
142 strcat(answer,str);
143 asn1_delete_structure(&value);
145 else{
146 len = sizeof(str2) - 1;
147 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",str2,&len);
148 if(!strcmp(str,str2)){
149 asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
150 len = sizeof(str) - 1;
151 asn1_read_value(cert,name3,str,&len);
152 asn1_der_decoding(&value,str,len,errorDescription);
153 len = sizeof(str) - 1;
154 asn1_read_value(value,"",str,&len); /* CHOICE */
155 strcpy(name3,str);
156 len = sizeof(str) - 1;
157 asn1_read_value(value,name3,str,&len);
158 str[len]=0;
159 strcat(answer," OU=");
160 strcat(answer,str);
161 asn1_delete_structure(&value);
166 k2++;
167 }while(1);
168 k++;
169 }while(1);
173 /******************************************************/
174 /* Function : create_certificate */
175 /* Description: creates a certificate named */
176 /* "certificate1". Values are the same */
177 /* as in rfc2459 Appendix D.1 */
178 /* Parameters: */
179 /* unsigned char *der: contains the der encoding */
180 /* int *der_len: number of bytes of der string */
181 /******************************************************/
182 void
183 create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
185 int result,k,len;
186 unsigned char str[1024],*str2;
187 ASN1_TYPE cert1=ASN1_TYPE_EMPTY;
188 ASN1_TYPE value=ASN1_TYPE_EMPTY;
189 ASN1_TYPE param=ASN1_TYPE_EMPTY;
190 ASN1_TYPE constr=ASN1_TYPE_EMPTY;
191 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
192 int max_len;
194 max_len=*der_len;
196 result=asn1_create_element(cert_def,"PKIX1Implicit88.Certificate",&cert1);
198 /* Use the next 3 lines to visit the empty certificate */
199 /* printf("-----------------\n");
200 asn1_visit_tree(cert1,"");
201 printf("-----------------\n"); */
203 /* version: v3(2) */
204 result=asn1_write_value(cert1,"tbsCertificate.version","v3",0);
206 /* serialNumber: 17 */
207 result=asn1_write_value(cert1,"tbsCertificate.serialNumber","17",0);
209 /* signature: dsa-with-sha1 */
210 len = sizeof(str) - 1;
211 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
212 result=asn1_write_value(cert1,"tbsCertificate.signature.algorithm",
213 str,1);
215 result=asn1_write_value(cert1,"tbsCertificate.signature.parameters",
216 NULL,0);
219 /* issuer: Country="US" Organization="gov" OrganizationUnit="nist" */
220 result=asn1_write_value(cert1,"tbsCertificate.issuer","rdnSequence",12);
222 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence","NEW",1);
223 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
224 /* C */
225 len = sizeof(str) - 1;
226 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
227 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
228 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName",
229 &value);
230 result=asn1_write_value(value,"","US",2);
231 *der_len = max_len;
232 result=asn1_der_coding(value,"",der,der_len,errorDescription);
233 asn1_delete_structure(&value);
234 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
237 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence","NEW",1);
238 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
239 /* O */
240 len = sizeof(str) - 1;
241 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
242 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
243 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName",
244 &value);
245 result=asn1_write_value(value,"","printableString",1);
246 result=asn1_write_value(value,"printableString","gov",3);
247 *der_len = max_len;
248 result=asn1_der_coding(value,"",der,der_len,errorDescription);
249 asn1_delete_structure(&value);
250 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
253 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence","NEW",1);
254 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
256 /* OU */
257 len = sizeof(str) - 1;
258 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
259 str,&len);
260 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
261 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
262 result=asn1_write_value(value,"","printableString",1);
263 result=asn1_write_value(value,"printableString","nist",4);
264 *der_len = max_len;
265 result=asn1_der_coding(value,"",der,der_len,errorDescription);
266 asn1_delete_structure(&value);
267 result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
270 /* validity */
271 result=asn1_write_value(cert1,"tbsCertificate.validity.notBefore","utcTime",1);
272 result=asn1_write_value(cert1,"tbsCertificate.validity.notBefore.utcTime","970630000000Z",1);
274 result=asn1_write_value(cert1,"tbsCertificate.validity.notAfter","utcTime",1);
275 result=asn1_write_value(cert1,"tbsCertificate.validity.notAfter.utcTime","971231000000Z",1);
279 /* subject: Country="US" Organization="gov" OrganizationUnit="nist" */
280 result=asn1_write_value(cert1,"tbsCertificate.subject","rdnSequence",1);
282 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence","NEW",1);
283 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST","NEW",1);
284 /* C */
285 len = sizeof(str) - 1;
286 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
287 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
288 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName",
289 &value);
290 result=asn1_write_value(value,"","US",2);
291 *der_len = max_len;
292 result=asn1_der_coding(value,"",der,der_len,errorDescription);
293 asn1_delete_structure(&value);
294 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
297 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence","NEW",4);
298 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
299 /* O */
300 len = sizeof(str) - 1;
301 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
302 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
303 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationName",
304 &value);
305 result=asn1_write_value(value,"","printableString",1);
306 result=asn1_write_value(value,"printableString","gov",3);
307 *der_len = max_len;
308 result=asn1_der_coding(value,"",der,der_len,errorDescription);
309 asn1_delete_structure(&value);
310 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
313 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence","NEW",4);
314 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
315 /* OU */
316 len = sizeof(str) - 1;
317 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
318 str,&len);
319 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
320 result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
321 result=asn1_write_value(value,"","printableString",1);
322 result=asn1_write_value(value,"printableString","nist",4);
323 *der_len = max_len;
324 result=asn1_der_coding(value,"",der,der_len,errorDescription);
325 asn1_delete_structure(&value);
326 result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
329 /* subjectPublicKeyInfo: dsa with parameters=Dss-Parms */
330 len = sizeof(str) - 1;
331 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa",str,&len);
332 result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm",str,1);
333 result=asn1_create_element(cert_def,"PKIX1Implicit88.Dss-Parms",&param);
334 str2="\xd4\x38"; /* only an example */
335 result=asn1_write_value(param,"p",str2,128);
336 str2="\xd4\x38"; /* only an example */
337 result=asn1_write_value(param,"q",str2,20);
338 str2="\xd4\x38"; /* only an example */
339 result=asn1_write_value(param,"g",str2,128);
340 *der_len = max_len;
341 result=asn1_der_coding(param,"",der,der_len,errorDescription);
342 asn1_delete_structure(&param);
343 result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",der,*der_len);
346 /* subjectPublicKey */
347 str2="\x02\x81"; /* only an example */
348 result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",str2,1048);
350 result=asn1_write_value(cert1,"tbsCertificate.issuerUniqueID",NULL,0); /* NO OPTION */
351 result=asn1_write_value(cert1,"tbsCertificate.subjectUniqueID",NULL,0); /* NO OPTION */
353 /* extensions */
354 result=asn1_write_value(cert1,"tbsCertificate.extensions","NEW",1);
355 len = sizeof(str) - 1;
356 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-basicConstraints",
357 str,&len);
358 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnID",str,1); /* basicConstraints */
359 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.critical","TRUE",1);
360 result=asn1_create_element(cert_def,"PKIX1Implicit88.BasicConstraints",&constr);
361 result=asn1_write_value(constr,"cA","TRUE",1);
362 result=asn1_write_value(constr,"pathLenConstraint",NULL,0);
363 *der_len = max_len;
364 result=asn1_der_coding(constr,"",der,der_len,errorDescription);
365 result=asn1_delete_structure(&constr);
366 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnValue",der,*der_len);
369 result=asn1_write_value(cert1,"tbsCertificate.extensions","NEW",1);
370 len = sizeof(str) - 1;
371 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-subjectKeyIdentifier",
372 str,&len);
373 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnID",str,1); /* subjectKeyIdentifier */
374 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.critical","FALSE",1);
375 str2="\x04\x14\xe7\x26\xc5"; /* only an example */
376 result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnValue",str2,22);
379 /* signatureAlgorithm: dsa-with-sha */
380 len = sizeof(str) - 1;
381 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
382 result=asn1_write_value(cert1,"signatureAlgorithm.algorithm",str,1);
383 result=asn1_write_value(cert1,"signatureAlgorithm.parameters",NULL,0); /* NO OPTION */
386 /* signature */
387 *der_len = max_len;
388 result=asn1_der_coding(cert1,"tbsCertificate",der,der_len
389 ,errorDescription);
390 if(result!=ASN1_SUCCESS){
391 printf("\n'tbsCertificate' encoding creation: ERROR\n");
393 /* add the lines for the signature on der[0]..der[der_len-1]: result in str2 */
394 result=asn1_write_value(cert1,"signature",str2,368); /* dsa-with-sha */
397 /* Use the next 3 lines to visit the certificate */
398 /* printf("-----------------\n");
399 asn1_visit_tree(cert1,"");
400 printf("-----------------\n"); */
402 *der_len = max_len;
403 result=asn1_der_coding(cert1,"",der,der_len,errorDescription);
404 if(result!=ASN1_SUCCESS){
405 printf("\n'certificate' encoding creation: ERROR\n");
406 return;
409 /* Print the 'Certificate1' DER encoding */
410 printf("-----------------\nCertificate Encoding:\nNumber of bytes=%i\n",*der_len);
411 for(k=0;k<*der_len;k++) printf("%02x ",der[k]);
412 printf("\n-----------------\n");
414 /* Clear the "certificate1" structure */
415 asn1_delete_structure(&cert1);
420 /******************************************************/
421 /* Function : get_certificate */
422 /* Description: creates a certificate named */
423 /* "certificate2" from a der encoding */
424 /* string */
425 /* Parameters: */
426 /* unsigned char *der: the encoding string */
427 /* int der_len: number of bytes of der string */
428 /******************************************************/
429 void
430 get_certificate(node_asn *cert_def,unsigned char *der,int der_len)
432 int result,len,start,end;
433 unsigned char str[1024],str2[1024];
434 ASN1_TYPE cert2=ASN1_TYPE_EMPTY;
435 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
437 asn1_create_element(cert_def,"PKIX1Implicit88.Certificate",&cert2);
439 result=asn1_der_decoding(&cert2,der,der_len,errorDescription);
441 if(result!=ASN1_SUCCESS){
442 printf("Problems with DER encoding\n");
443 return;
447 /* issuer */
448 get_Name_type(cert_def,cert2,"tbsCertificate.issuer",str);
449 printf("certificate:\nissuer :%s\n",str);
450 /* subject */
451 get_Name_type(cert_def,cert2,"tbsCertificate.subject",str);
452 printf("subject:%s\n",str);
455 /* Verify sign */
456 len = sizeof(str) - 1;
457 result=asn1_read_value(cert2,"signatureAlgorithm.algorithm"
458 ,str,&len);
460 len = sizeof(str2) - 1;
461 result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str2,&len);
462 if(!strcmp(str,str2)){ /* dsa-with-sha */
464 result=asn1_der_decoding_startEnd(cert2,der,der_len,
465 "tbsCertificate",&start,&end);
467 /* add the lines to calculate the sha on der[start]..der[end] */
469 len = sizeof(str) - 1;
470 result=asn1_read_value(cert2,"signature",str,&len);
472 /* compare the previous value to signature ( with issuer public key) */
475 /* Use the next 3 lines to visit the certificate */
476 /* printf("-----------------\n");
477 asn1_visit_tree(cert2,"");
478 printf("-----------------\n"); */
481 /* Clear the "certificate2" structure */
482 asn1_delete_structure(&cert2);
485 #include "pkix_asn1_tab.c"
487 /********************************************************/
488 /* Function : main */
489 /* Description: reads the certificate description. */
490 /* Creates a certificate and calculate */
491 /* the der encoding. After that creates */
492 /* another certificate from der string */
493 /********************************************************/
495 main(int argc,char *argv[])
497 int result,der_len;
498 unsigned char der[1024];
499 ASN1_TYPE PKIX1Implicit88=ASN1_TYPE_EMPTY;
500 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
502 if(1)
503 result=asn1_array2tree(pkix_asn1_tab,&PKIX1Implicit88,errorDescription);
504 else
505 result=asn1_parser2tree("pkix.asn",&PKIX1Implicit88,errorDescription);
507 if(result != ASN1_SUCCESS){
508 libtasn1_perror(result);
509 printf("%s",errorDescription);
510 exit(1);
514 /* Use the following 3 lines to visit the PKIX1Implicit structures */
515 /* printf("-----------------\n");
516 asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88");
517 printf("-----------------\n"); */
519 der_len=1024;
520 create_certificate(PKIX1Implicit88,der,&der_len);
522 get_certificate(PKIX1Implicit88,der,der_len);
524 /* Clear the "PKIX1Implicit88" structures */
525 asn1_delete_structure(&PKIX1Implicit88);
527 return 0;