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
23 /*****************************************************/
24 /* File: CertificateExample.c */
25 /* Description: An example on how to use the ASN1 */
26 /* parser with the Certificate.txt file */
27 /*****************************************************/
36 my_ltostr(long v
,char *str
)
53 temp
[start
+count
]='0'+(char)r
;
58 for(k
=0;k
<count
;k
++) str
[k
+start
]=temp
[start
+count
-k
-1];
63 /******************************************************/
64 /* Function : get_name_type */
65 /* Description: analyze a structure of type Name */
67 /* char *root: the structure identifier */
68 /* char *answer: the string with elements like: */
70 /******************************************************/
72 get_Name_type(node_asn
*cert_def
,node_asn
*cert
,char *root
, char *answer
)
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
];
83 strcat(name
,".rdnSequence.?");
86 len
= sizeof(str
) - 1;
87 result
=asn1_read_value(cert
,name
,str
,&len
);
88 if(result
==ASN1_ELEMENT_NOT_FOUND
) break;
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;
99 strcat(name3
,".type");
100 len
= sizeof(str
) - 1;
101 result
=asn1_read_value(cert
,name3
,str
,&len
);
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",
108 if(!strcmp(str
,str2
)){
109 asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationName",
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 */
117 len
= sizeof(str
) - 1;
118 asn1_read_value(value
,name3
,str
,&len
);
120 strcat(answer
," C=");
122 asn1_delete_structure(&value
);
125 len
= sizeof(str2
) - 1;
126 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationName"
128 if(!strcmp(str
,str2
)){
129 asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationName"
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 */
137 len
= sizeof(str
) - 1;
138 asn1_read_value(value
,name3
,str
,&len
);
140 strcat(answer
," O=");
142 asn1_delete_structure(&value
);
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 */
155 len
= sizeof(str
) - 1;
156 asn1_read_value(value
,name3
,str
,&len
);
158 strcat(answer
," OU=");
160 asn1_delete_structure(&value
);
172 /******************************************************/
173 /* Function : create_certificate */
174 /* Description: creates a certificate named */
175 /* "certificate1". Values are the same */
176 /* as in rfc2459 Appendix D.1 */
178 /* unsigned char *der: contains the der encoding */
179 /* int *der_len: number of bytes of der string */
180 /******************************************************/
182 create_certificate(node_asn
*cert_def
,unsigned char *der
,int *der_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
];
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"); */
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",
214 result
=asn1_write_value(cert1
,"tbsCertificate.signature.parameters",
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);
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",
229 result
=asn1_write_value(value
,"","US",2);
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);
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",
244 result
=asn1_write_value(value
,"","printableString",1);
245 result
=asn1_write_value(value
,"printableString","gov",3);
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);
256 len
= sizeof(str
) - 1;
257 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationalUnitName",
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);
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
);
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);
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",
289 result
=asn1_write_value(value
,"","US",2);
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);
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",
304 result
=asn1_write_value(value
,"","printableString",1);
305 result
=asn1_write_value(value
,"printableString","gov",3);
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);
315 len
= sizeof(str
) - 1;
316 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationalUnitName",
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);
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",¶m
);
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);
340 result
=asn1_der_coding(param
,"",der
,der_len
,errorDescription
);
341 asn1_delete_structure(¶m
);
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 */
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",
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);
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",
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 */
387 result
=asn1_der_coding(cert1
,"tbsCertificate",der
,der_len
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"); */
402 result
=asn1_der_coding(cert1
,"",der
,der_len
,errorDescription
);
403 if(result
!=ASN1_SUCCESS
){
404 printf("\n'certificate' encoding creation: ERROR\n");
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 */
425 /* unsigned char *der: the encoding string */
426 /* int der_len: number of bytes of der string */
427 /******************************************************/
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");
447 get_Name_type(cert_def
,cert2
,"tbsCertificate.issuer",str
);
448 printf("certificate:\nissuer :%s\n",str
);
450 get_Name_type(cert_def
,cert2
,"tbsCertificate.subject",str
);
451 printf("subject:%s\n",str
);
455 len
= sizeof(str
) - 1;
456 result
=asn1_read_value(cert2
,"signatureAlgorithm.algorithm"
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
[])
497 unsigned char der
[1024];
498 ASN1_TYPE PKIX1Implicit88
=ASN1_TYPE_EMPTY
;
499 char errorDescription
[MAX_ERROR_DESCRIPTION_SIZE
];
502 result
=asn1_array2tree(pkix_asn1_tab
,&PKIX1Implicit88
,errorDescription
);
504 result
=asn1_parser2tree("pkix.asn",&PKIX1Implicit88
,errorDescription
);
506 if(result
!= ASN1_SUCCESS
){
507 libtasn1_perror(result
);
508 printf("%s",errorDescription
);
513 /* Use the following 3 lines to visit the PKIX1Implicit structures */
514 /* printf("-----------------\n");
515 asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88");
516 printf("-----------------\n"); */
519 create_certificate(PKIX1Implicit88
,der
,&der_len
);
521 get_certificate(PKIX1Implicit88
,der
,der_len
);
523 /* Clear the "PKIX1Implicit88" structures */
524 asn1_delete_structure(&PKIX1Implicit88
);