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
24 /*****************************************************/
25 /* File: CertificateExample.c */
26 /* Description: An example on how to use the ASN1 */
27 /* parser with the Certificate.txt file */
28 /*****************************************************/
37 my_ltostr(long v
,char *str
)
54 temp
[start
+count
]='0'+(char)r
;
59 for(k
=0;k
<count
;k
++) str
[k
+start
]=temp
[start
+count
-k
-1];
64 /******************************************************/
65 /* Function : get_name_type */
66 /* Description: analyze a structure of type Name */
68 /* char *root: the structure identifier */
69 /* char *answer: the string with elements like: */
71 /******************************************************/
73 get_Name_type(node_asn
*cert_def
,node_asn
*cert
,char *root
, char *answer
)
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
];
84 strcat(name
,".rdnSequence.?");
87 len
= sizeof(str
) - 1;
88 result
=asn1_read_value(cert
,name
,str
,&len
);
89 if(result
==ASN1_ELEMENT_NOT_FOUND
) break;
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;
100 strcat(name3
,".type");
101 len
= sizeof(str
) - 1;
102 result
=asn1_read_value(cert
,name3
,str
,&len
);
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",
109 if(!strcmp(str
,str2
)){
110 asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationName",
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 */
118 len
= sizeof(str
) - 1;
119 asn1_read_value(value
,name3
,str
,&len
);
121 strcat(answer
," C=");
123 asn1_delete_structure(&value
);
126 len
= sizeof(str2
) - 1;
127 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationName"
129 if(!strcmp(str
,str2
)){
130 asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationName"
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 */
138 len
= sizeof(str
) - 1;
139 asn1_read_value(value
,name3
,str
,&len
);
141 strcat(answer
," O=");
143 asn1_delete_structure(&value
);
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 */
156 len
= sizeof(str
) - 1;
157 asn1_read_value(value
,name3
,str
,&len
);
159 strcat(answer
," OU=");
161 asn1_delete_structure(&value
);
173 /******************************************************/
174 /* Function : create_certificate */
175 /* Description: creates a certificate named */
176 /* "certificate1". Values are the same */
177 /* as in rfc2459 Appendix D.1 */
179 /* unsigned char *der: contains the der encoding */
180 /* int *der_len: number of bytes of der string */
181 /******************************************************/
183 create_certificate(node_asn
*cert_def
,unsigned char *der
,int *der_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
];
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"); */
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",
215 result
=asn1_write_value(cert1
,"tbsCertificate.signature.parameters",
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);
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",
230 result
=asn1_write_value(value
,"","US",2);
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);
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",
245 result
=asn1_write_value(value
,"","printableString",1);
246 result
=asn1_write_value(value
,"printableString","gov",3);
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);
257 len
= sizeof(str
) - 1;
258 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationalUnitName",
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);
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
);
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);
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",
290 result
=asn1_write_value(value
,"","US",2);
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);
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",
305 result
=asn1_write_value(value
,"","printableString",1);
306 result
=asn1_write_value(value
,"printableString","gov",3);
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);
316 len
= sizeof(str
) - 1;
317 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationalUnitName",
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);
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",¶m
);
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);
341 result
=asn1_der_coding(param
,"",der
,der_len
,errorDescription
);
342 asn1_delete_structure(¶m
);
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 */
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",
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);
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",
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 */
388 result
=asn1_der_coding(cert1
,"tbsCertificate",der
,der_len
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"); */
403 result
=asn1_der_coding(cert1
,"",der
,der_len
,errorDescription
);
404 if(result
!=ASN1_SUCCESS
){
405 printf("\n'certificate' encoding creation: ERROR\n");
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 */
426 /* unsigned char *der: the encoding string */
427 /* int der_len: number of bytes of der string */
428 /******************************************************/
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");
448 get_Name_type(cert_def
,cert2
,"tbsCertificate.issuer",str
);
449 printf("certificate:\nissuer :%s\n",str
);
451 get_Name_type(cert_def
,cert2
,"tbsCertificate.subject",str
);
452 printf("subject:%s\n",str
);
456 len
= sizeof(str
) - 1;
457 result
=asn1_read_value(cert2
,"signatureAlgorithm.algorithm"
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
[])
498 unsigned char der
[1024];
499 ASN1_TYPE PKIX1Implicit88
=ASN1_TYPE_EMPTY
;
500 char errorDescription
[MAX_ERROR_DESCRIPTION_SIZE
];
503 result
=asn1_array2tree(pkix_asn1_tab
,&PKIX1Implicit88
,errorDescription
);
505 result
=asn1_parser2tree("pkix.asn",&PKIX1Implicit88
,errorDescription
);
507 if(result
!= ASN1_SUCCESS
){
508 libtasn1_perror(result
);
509 printf("%s",errorDescription
);
514 /* Use the following 3 lines to visit the PKIX1Implicit structures */
515 /* printf("-----------------\n");
516 asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88");
517 printf("-----------------\n"); */
520 create_certificate(PKIX1Implicit88
,der
,&der_len
);
522 get_certificate(PKIX1Implicit88
,der
,der_len
);
524 /* Clear the "PKIX1Implicit88" structures */
525 asn1_delete_structure(&PKIX1Implicit88
);