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 /*****************************************************/
35 my_ltostr(long v
,char *str
)
52 temp
[start
+count
]='0'+(char)r
;
57 for(k
=0;k
<count
;k
++) str
[k
+start
]=temp
[start
+count
-k
-1];
62 /******************************************************/
63 /* Function : get_name_type */
64 /* Description: analyze a structure of type Name */
66 /* char *root: the structure identifier */
67 /* char *answer: the string with elements like: */
69 /******************************************************/
71 get_Name_type(node_asn
*cert_def
,node_asn
*cert
,char *root
, char *answer
)
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
];
82 strcat(name
,".rdnSequence.?");
85 len
= sizeof(str
) - 1;
86 result
=asn1_read_value(cert
,name
,str
,&len
);
87 if(result
==ASN1_ELEMENT_NOT_FOUND
) break;
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;
98 strcat(name3
,".type");
99 len
= sizeof(str
) - 1;
100 result
=asn1_read_value(cert
,name3
,str
,&len
);
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",
107 if(!strcmp(str
,str2
)){
108 asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationName",
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 */
116 len
= sizeof(str
) - 1;
117 asn1_read_value(value
,name3
,str
,&len
);
119 strcat(answer
," C=");
121 asn1_delete_structure(&value
);
124 len
= sizeof(str2
) - 1;
125 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationName"
127 if(!strcmp(str
,str2
)){
128 asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationName"
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 */
136 len
= sizeof(str
) - 1;
137 asn1_read_value(value
,name3
,str
,&len
);
139 strcat(answer
," O=");
141 asn1_delete_structure(&value
);
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 */
154 len
= sizeof(str
) - 1;
155 asn1_read_value(value
,name3
,str
,&len
);
157 strcat(answer
," OU=");
159 asn1_delete_structure(&value
);
171 /******************************************************/
172 /* Function : create_certificate */
173 /* Description: creates a certificate named */
174 /* "certificate1". Values are the same */
175 /* as in rfc2459 Appendix D.1 */
177 /* unsigned char *der: contains the der encoding */
178 /* int *der_len: number of bytes of der string */
179 /******************************************************/
181 create_certificate(node_asn
*cert_def
,unsigned char *der
,int *der_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
];
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"); */
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",
213 result
=asn1_write_value(cert1
,"tbsCertificate.signature.parameters",
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);
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",
228 result
=asn1_write_value(value
,"","US",2);
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);
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",
243 result
=asn1_write_value(value
,"","printableString",1);
244 result
=asn1_write_value(value
,"printableString","gov",3);
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);
255 len
= sizeof(str
) - 1;
256 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationalUnitName",
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);
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
);
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);
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",
288 result
=asn1_write_value(value
,"","US",2);
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);
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",
303 result
=asn1_write_value(value
,"","printableString",1);
304 result
=asn1_write_value(value
,"printableString","gov",3);
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);
314 len
= sizeof(str
) - 1;
315 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationalUnitName",
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);
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",¶m
);
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);
339 result
=asn1_der_coding(param
,"",der
,der_len
,errorDescription
);
340 asn1_delete_structure(¶m
);
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 */
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",
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);
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",
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 */
386 result
=asn1_der_coding(cert1
,"tbsCertificate",der
,der_len
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"); */
401 result
=asn1_der_coding(cert1
,"",der
,der_len
,errorDescription
);
402 if(result
!=ASN1_SUCCESS
){
403 printf("\n'certificate' encoding creation: ERROR\n");
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 */
424 /* unsigned char *der: the encoding string */
425 /* int der_len: number of bytes of der string */
426 /******************************************************/
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");
446 get_Name_type(cert_def
,cert2
,"tbsCertificate.issuer",str
);
447 printf("certificate:\nissuer :%s\n",str
);
449 get_Name_type(cert_def
,cert2
,"tbsCertificate.subject",str
);
450 printf("subject:%s\n",str
);
454 len
= sizeof(str
) - 1;
455 result
=asn1_read_value(cert2
,"signatureAlgorithm.algorithm"
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
[])
496 unsigned char der
[1024];
497 ASN1_TYPE PKIX1Implicit88
=ASN1_TYPE_EMPTY
;
498 char errorDescription
[MAX_ERROR_DESCRIPTION_SIZE
];
501 result
=asn1_array2tree(pkix_asn1_tab
,&PKIX1Implicit88
,errorDescription
);
503 result
=asn1_parser2tree("pkix.asn",&PKIX1Implicit88
,errorDescription
);
505 if(result
!= ASN1_SUCCESS
){
506 libtasn1_perror(result
);
507 printf("%s",errorDescription
);
512 /* Use the following 3 lines to visit the PKIX1Implicit structures */
513 /* printf("-----------------\n");
514 asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88");
515 printf("-----------------\n"); */
518 create_certificate(PKIX1Implicit88
,der
,&der_len
);
520 get_certificate(PKIX1Implicit88
,der
,der_len
);
522 /* Clear the "PKIX1Implicit88" structures */
523 asn1_delete_structure(&PKIX1Implicit88
);