2 * Copyright (C) 2000,2001 Fabio Fiorina
4 * This file is part of GNUTLS.
6 * GNUTLS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
22 /*****************************************************/
23 /* File: CertificateExample.c */
24 /* Description: An example on how to use the ASN1 */
25 /* parser with the Certificate.txt file */
26 /*****************************************************/
34 my_ltostr(long v
,char *str
)
51 temp
[start
+count
]='0'+(char)r
;
56 for(k
=0;k
<count
;k
++) str
[k
+start
]=temp
[start
+count
-k
-1];
61 /******************************************************/
62 /* Function : get_name_type */
63 /* Description: analyze a structure of type Name */
65 /* char *root: the structure identifier */
66 /* char *answer: the string with elements like: */
68 /******************************************************/
70 get_Name_type(node_asn
*cert_def
,node_asn
*cert
,char *root
, char *answer
)
73 char name
[128],str
[1024],str2
[1024],name2
[128],counter
[5],name3
[128];
74 ASN1_TYPE value
=ASN1_TYPE_EMPTY
;
75 char errorDescription
[MAX_ERROR_DESCRIPTION_SIZE
];
81 strcat(name
,".rdnSequence.?");
84 len
= sizeof(str
) - 1;
85 result
=asn1_read_value(cert
,name
,str
,&len
);
86 if(result
==ASN1_ELEMENT_NOT_FOUND
) break;
91 my_ltostr(k2
,counter
);
92 strcat(name2
,counter
);
93 len
= sizeof(str
) - 1;
94 result
=asn1_read_value(cert
,name2
,str
,&len
);
95 if(result
==ASN1_ELEMENT_NOT_FOUND
) break;
97 strcat(name3
,".type");
98 len
= sizeof(str
) - 1;
99 result
=asn1_read_value(cert
,name3
,str
,&len
);
101 strcat(name3
,".value");
102 if(result
==ASN1_SUCCESS
){
103 len
= sizeof(str2
) - 1;
104 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-countryName",
106 if(!strcmp(str
,str2
)){
107 asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationName",
109 len
= sizeof(str
) - 1;
110 asn1_read_value(cert
,name3
,str
,&len
);
111 asn1_der_decoding(&value
,str
,len
,errorDescription
);
112 len
= sizeof(str
) - 1;
113 asn1_read_value(value
,"",str
,&len
); /* CHOICE */
115 len
= sizeof(str
) - 1;
116 asn1_read_value(value
,name3
,str
,&len
);
118 strcat(answer
," C=");
120 asn1_delete_structure(&value
);
123 len
= sizeof(str2
) - 1;
124 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationName"
126 if(!strcmp(str
,str2
)){
127 asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationName"
129 len
= sizeof(str
) - 1;
130 asn1_read_value(cert
,name3
,str
,&len
);
131 asn1_der_decoding(&value
,str
,len
,errorDescription
);
132 len
= sizeof(str
) - 1;
133 asn1_read_value(value
,"",str
,&len
); /* CHOICE */
135 len
= sizeof(str
) - 1;
136 asn1_read_value(value
,name3
,str
,&len
);
138 strcat(answer
," O=");
140 asn1_delete_structure(&value
);
143 len
= sizeof(str2
) - 1;
144 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationalUnitName",str2
,&len
);
145 if(!strcmp(str
,str2
)){
146 asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationalUnitName",&value
);
147 len
= sizeof(str
) - 1;
148 asn1_read_value(cert
,name3
,str
,&len
);
149 asn1_der_decoding(&value
,str
,len
,errorDescription
);
150 len
= sizeof(str
) - 1;
151 asn1_read_value(value
,"",str
,&len
); /* CHOICE */
153 len
= sizeof(str
) - 1;
154 asn1_read_value(value
,name3
,str
,&len
);
156 strcat(answer
," OU=");
158 asn1_delete_structure(&value
);
170 /******************************************************/
171 /* Function : create_certificate */
172 /* Description: creates a certificate named */
173 /* "certificate1". Values are the same */
174 /* as in rfc2459 Appendix D.1 */
176 /* unsigned char *der: contains the der encoding */
177 /* int *der_len: number of bytes of der string */
178 /******************************************************/
180 create_certificate(node_asn
*cert_def
,unsigned char *der
,int *der_len
)
183 unsigned char str
[1024],*str2
;
184 ASN1_TYPE cert1
=ASN1_TYPE_EMPTY
;
185 ASN1_TYPE value
=ASN1_TYPE_EMPTY
;
186 ASN1_TYPE param
=ASN1_TYPE_EMPTY
;
187 ASN1_TYPE constr
=ASN1_TYPE_EMPTY
;
188 char errorDescription
[MAX_ERROR_DESCRIPTION_SIZE
];
190 result
=asn1_create_element(cert_def
,"PKIX1Implicit88.Certificate",&cert1
);
192 /* Use the next 3 lines to visit the empty certificate */
193 /* printf("-----------------\n");
194 asn1_visit_tree(cert1,"");
195 printf("-----------------\n"); */
198 result
=asn1_write_value(cert1
,"tbsCertificate.version","v3",0);
200 /* serialNumber: 17 */
201 result
=asn1_write_value(cert1
,"tbsCertificate.serialNumber","17",0);
203 /* signature: dsa-with-sha1 */
204 len
= sizeof(str
) - 1;
205 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-dsa-with-sha1",str
,&len
);
206 result
=asn1_write_value(cert1
,"tbsCertificate.signature.algorithm",
209 result
=asn1_write_value(cert1
,"tbsCertificate.signature.parameters",
213 /* issuer: Country="US" Organization="gov" OrganizationUnit="nist" */
214 result
=asn1_write_value(cert1
,"tbsCertificate.issuer","rdnSequence",12);
216 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence","NEW",1);
217 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
219 len
= sizeof(str
) - 1;
220 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-countryName",str
,&len
);
221 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str
,1);
222 result
=asn1_create_element(cert_def
,"PKIX1Implicit88.X520countryName",
224 result
=asn1_write_value(value
,"","US",2);
225 result
=asn1_der_coding(value
,"",der
,der_len
,errorDescription
);
226 asn1_delete_structure(&value
);
227 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der
,*der_len
);
230 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence","NEW",1);
231 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
233 len
= sizeof(str
) - 1;
234 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationName",str
,&len
);
235 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str
,1);
236 result
=asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationName",
238 result
=asn1_write_value(value
,"","printableString",1);
239 result
=asn1_write_value(value
,"printableString","gov",3);
240 result
=asn1_der_coding(value
,"",der
,der_len
,errorDescription
);
241 asn1_delete_structure(&value
);
242 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der
,*der_len
);
245 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence","NEW",1);
246 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
249 len
= sizeof(str
) - 1;
250 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationalUnitName",
252 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str
,1);
253 result
=asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationalUnitName",&value
);
254 result
=asn1_write_value(value
,"","printableString",1);
255 result
=asn1_write_value(value
,"printableString","nist",4);
256 result
=asn1_der_coding(value
,"",der
,der_len
,errorDescription
);
257 asn1_delete_structure(&value
);
258 result
=asn1_write_value(cert1
,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der
,*der_len
);
262 result
=asn1_write_value(cert1
,"tbsCertificate.validity.notBefore","utcTime",1);
263 result
=asn1_write_value(cert1
,"tbsCertificate.validity.notBefore.utcTime","970630000000Z",1);
265 result
=asn1_write_value(cert1
,"tbsCertificate.validity.notAfter","utcTime",1);
266 result
=asn1_write_value(cert1
,"tbsCertificate.validity.notAfter.utcTime","971231000000Z",1);
270 /* subject: Country="US" Organization="gov" OrganizationUnit="nist" */
271 result
=asn1_write_value(cert1
,"tbsCertificate.subject","rdnSequence",1);
273 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence","NEW",1);
274 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence.?LAST","NEW",1);
276 len
= sizeof(str
) - 1;
277 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-countryName",str
,&len
);
278 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str
,1);
279 result
=asn1_create_element(cert_def
,"PKIX1Implicit88.X520countryName",
281 result
=asn1_write_value(value
,"","US",2);
282 result
=asn1_der_coding(value
,"",der
,der_len
,errorDescription
);
283 asn1_delete_structure(&value
);
284 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der
,*der_len
);
287 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence","NEW",4);
288 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
290 len
= sizeof(str
) - 1;
291 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationName",str
,&len
);
292 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str
,1);
293 result
=asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationName",
295 result
=asn1_write_value(value
,"","printableString",1);
296 result
=asn1_write_value(value
,"printableString","gov",3);
297 result
=asn1_der_coding(value
,"",der
,der_len
,errorDescription
);
298 asn1_delete_structure(&value
);
299 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der
,*der_len
);
302 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence","NEW",4);
303 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
305 len
= sizeof(str
) - 1;
306 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-at-organizationalUnitName",
308 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str
,1);
309 result
=asn1_create_element(cert_def
,"PKIX1Implicit88.X520OrganizationalUnitName",&value
);
310 result
=asn1_write_value(value
,"","printableString",1);
311 result
=asn1_write_value(value
,"printableString","nist",4);
312 result
=asn1_der_coding(value
,"",der
,der_len
,errorDescription
);
313 asn1_delete_structure(&value
);
314 result
=asn1_write_value(cert1
,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der
,*der_len
);
317 /* subjectPublicKeyInfo: dsa with parameters=Dss-Parms */
318 len
= sizeof(str
) - 1;
319 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-dsa",str
,&len
);
320 result
=asn1_write_value(cert1
,"tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm",str
,1);
321 result
=asn1_create_element(cert_def
,"PKIX1Implicit88.Dss-Parms",¶m
);
322 str2
="\xd4\x38"; /* only an example */
323 result
=asn1_write_value(param
,"p",str2
,128);
324 str2
="\xd4\x38"; /* only an example */
325 result
=asn1_write_value(param
,"q",str2
,20);
326 str2
="\xd4\x38"; /* only an example */
327 result
=asn1_write_value(param
,"g",str2
,128);
328 result
=asn1_der_coding(param
,"",der
,der_len
,errorDescription
);
329 asn1_delete_structure(¶m
);
330 result
=asn1_write_value(cert1
,"tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",der
,*der_len
);
333 /* subjectPublicKey */
334 str2
="\x02\x81"; /* only an example */
335 result
=asn1_write_value(cert1
,"tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",str2
,1048);
337 result
=asn1_write_value(cert1
,"tbsCertificate.issuerUniqueID",NULL
,0); /* NO OPTION */
338 result
=asn1_write_value(cert1
,"tbsCertificate.subjectUniqueID",NULL
,0); /* NO OPTION */
341 result
=asn1_write_value(cert1
,"tbsCertificate.extensions","NEW",1);
342 len
= sizeof(str
) - 1;
343 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-ce-basicConstraints",
345 result
=asn1_write_value(cert1
,"tbsCertificate.extensions.?LAST.extnID",str
,1); /* basicConstraints */
346 result
=asn1_write_value(cert1
,"tbsCertificate.extensions.?LAST.critical","TRUE",1);
347 result
=asn1_create_element(cert_def
,"PKIX1Implicit88.BasicConstraints",&constr
);
348 result
=asn1_write_value(constr
,"cA","TRUE",1);
349 result
=asn1_write_value(constr
,"pathLenConstraint",NULL
,0);
350 result
=asn1_der_coding(constr
,"",der
,der_len
,errorDescription
);
351 result
=asn1_delete_structure(&constr
);
352 result
=asn1_write_value(cert1
,"tbsCertificate.extensions.?LAST.extnValue",der
,*der_len
);
355 result
=asn1_write_value(cert1
,"tbsCertificate.extensions","NEW",1);
356 len
= sizeof(str
) - 1;
357 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-ce-subjectKeyIdentifier",
359 result
=asn1_write_value(cert1
,"tbsCertificate.extensions.?LAST.extnID",str
,1); /* subjectKeyIdentifier */
360 result
=asn1_write_value(cert1
,"tbsCertificate.extensions.?LAST.critical","FALSE",1);
361 str2
="\x04\x14\xe7\x26\xc5"; /* only an example */
362 result
=asn1_write_value(cert1
,"tbsCertificate.extensions.?LAST.extnValue",str2
,22);
365 /* signatureAlgorithm: dsa-with-sha */
366 len
= sizeof(str
) - 1;
367 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-dsa-with-sha1",str
,&len
);
368 result
=asn1_write_value(cert1
,"signatureAlgorithm.algorithm",str
,1);
369 result
=asn1_write_value(cert1
,"signatureAlgorithm.parameters",NULL
,0); /* NO OPTION */
373 result
=asn1_der_coding(cert1
,"tbsCertificate",der
,der_len
375 if(result
!=ASN1_SUCCESS
){
376 printf("\n'tbsCertificate' encoding creation: ERROR\n");
378 /* add the lines for the signature on der[0]..der[der_len-1]: result in str2 */
379 result
=asn1_write_value(cert1
,"signature",str2
,368); /* dsa-with-sha */
382 /* Use the next 3 lines to visit the certificate */
383 /* printf("-----------------\n");
384 asn1_visit_tree(cert1,"");
385 printf("-----------------\n"); */
388 result
=asn1_der_coding(cert1
,"",der
,der_len
,errorDescription
);
389 if(result
!=ASN1_SUCCESS
){
390 printf("\n'certificate' encoding creation: ERROR\n");
394 /* Print the 'Certificate1' DER encoding */
395 printf("-----------------\nCertificate Encoding:\nNumber of bytes=%i\n",*der_len
);
396 for(k
=0;k
<*der_len
;k
++) printf("%02x ",der
[k
]);
397 printf("\n-----------------\n");
399 /* Clear the "certificate1" structure */
400 asn1_delete_structure(&cert1
);
405 /******************************************************/
406 /* Function : get_certificate */
407 /* Description: creates a certificate named */
408 /* "certificate2" from a der encoding */
411 /* unsigned char *der: the encoding string */
412 /* int der_len: number of bytes of der string */
413 /******************************************************/
415 get_certificate(node_asn
*cert_def
,unsigned char *der
,int der_len
)
417 int result
,len
,start
,end
;
418 unsigned char str
[1024],str2
[1024];
419 ASN1_TYPE cert2
=ASN1_TYPE_EMPTY
;
420 char errorDescription
[MAX_ERROR_DESCRIPTION_SIZE
];
422 asn1_create_element(cert_def
,"PKIX1Implicit88.Certificate",&cert2
);
424 result
=asn1_der_decoding(&cert2
,der
,der_len
,errorDescription
);
426 if(result
!=ASN1_SUCCESS
){
427 printf("Problems with DER encoding\n");
433 get_Name_type(cert_def
,cert2
,"tbsCertificate.issuer",str
);
434 printf("certificate:\nissuer :%s\n",str
);
436 get_Name_type(cert_def
,cert2
,"tbsCertificate.subject",str
);
437 printf("subject:%s\n",str
);
441 len
= sizeof(str
) - 1;
442 result
=asn1_read_value(cert2
,"signatureAlgorithm.algorithm"
445 len
= sizeof(str2
) - 1;
446 result
=asn1_read_value(cert_def
,"PKIX1Implicit88.id-dsa-with-sha1",str2
,&len
);
447 if(!strcmp(str
,str2
)){ /* dsa-with-sha */
449 result
=asn1_der_decoding_startEnd(cert2
,der
,der_len
,
450 "tbsCertificate",&start
,&end
);
452 /* add the lines to calculate the sha on der[start]..der[end] */
454 len
= sizeof(str
) - 1;
455 result
=asn1_read_value(cert2
,"signature",str
,&len
);
457 /* compare the previous value to signature ( with issuer public key) */
460 /* Use the next 3 lines to visit the certificate */
461 /* printf("-----------------\n");
462 asn1_visit_tree(cert2,"");
463 printf("-----------------\n"); */
466 /* Clear the "certificate2" structure */
467 asn1_delete_structure(&cert2
);
470 #include "pkix_asn1_tab.c"
472 /********************************************************/
473 /* Function : main */
474 /* Description: reads the certificate description. */
475 /* Creates a certificate and calculate */
476 /* the der encoding. After that creates */
477 /* another certificate from der string */
478 /********************************************************/
480 main(int argc
,char *argv
[])
483 unsigned char der
[1024];
484 ASN1_TYPE PKIX1Implicit88
=ASN1_TYPE_EMPTY
;
485 char errorDescription
[MAX_ERROR_DESCRIPTION_SIZE
];
488 result
=asn1_array2tree(pkix_asn1_tab
,&PKIX1Implicit88
,errorDescription
);
490 result
=asn1_parser2tree("pkix.asn",&PKIX1Implicit88
,errorDescription
);
492 if(result
!= ASN1_SUCCESS
){
493 libtasn1_perror(result
);
494 printf("%s",errorDescription
);
499 /* Use the following 3 lines to visit the PKIX1Implicit structures */
500 /* printf("-----------------\n");
501 asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88");
502 printf("-----------------\n"); */
505 create_certificate(PKIX1Implicit88
,der
,&der_len
);
507 get_certificate(PKIX1Implicit88
,der
,der_len
);
509 /* Clear the "PKIX1Implicit88" structures */
510 asn1_delete_structure(&PKIX1Implicit88
);