optimized _asn1_find_up().
[platform/upstream/libtasn1.git] / examples / CrlExample.c
1 /*
2  * Copyright (C) 2000-2014 Free Software Foundation, Inc.
3  *
4  * This file is part of LIBTASN1.
5  *
6  * This program 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 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 /*****************************************************/
22 /* File: CrlExample.c                                */
23 /* Description: An example on how to use the ASN1    */
24 /*              parser with the Certificate.txt file */
25 /*****************************************************/
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include "libtasn1.h"
31
32
33
34 static char *
35 my_ltostr (long v, char *str)
36 {
37   long d, r;
38   char temp[20];
39   int count, k, start;
40
41   if (v < 0)
42     {
43       str[0] = '-';
44       start = 1;
45       v = -v;
46     }
47   else
48     start = 0;
49
50   count = 0;
51   do
52     {
53       d = v / 10;
54       r = v - d * 10;
55       temp[start + count] = '0' + (char) r;
56       count++;
57       v = d;
58     }
59   while (v);
60
61   for (k = 0; k < count; k++)
62     str[k + start] = temp[start + count - k - 1];
63   str[count + start] = 0;
64   return str;
65 }
66
67
68 /******************************************************/
69 /* Function : get_name_type                           */
70 /* Description: analyze a structure of type Name      */
71 /* Parameters:                                        */
72 /*   char *root: the structure identifier             */
73 /*   char *answer: the string with elements like:     */
74 /*                 "C=US O=gov"                       */
75 /******************************************************/
76 static void
77 get_Name_type (ASN1_TYPE cert_def, ASN1_TYPE cert, const char *root,
78                unsigned char *ans)
79 {
80   int k, k2, result, len;
81   char name[128], str[1024], str2[1024], name2[128], counter[5], name3[128];
82   ASN1_TYPE value = ASN1_TYPE_EMPTY;
83   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
84   char *answer = (char *) ans;
85
86   answer[0] = 0;
87   k = 1;
88   do
89     {
90       strcpy (name, root);
91       strcat (name, ".rdnSequence.?");
92       my_ltostr (k, counter);
93       strcat (name, counter);
94
95       len = sizeof (str) - 1;
96       result = asn1_read_value (cert, name, str, &len);
97       if (result == ASN1_ELEMENT_NOT_FOUND)
98         break;
99       k2 = 1;
100       do
101         {
102           strcpy (name2, name);
103           strcat (name2, ".?");
104           my_ltostr (k2, counter);
105           strcat (name2, counter);
106
107           len = sizeof (str) - 1;
108           result = asn1_read_value (cert, name2, str, &len);
109           if (result == ASN1_ELEMENT_NOT_FOUND)
110             break;
111           strcpy (name3, name2);
112           strcat (name3, ".type");
113
114           len = sizeof (str) - 1;
115           result = asn1_read_value (cert, name3, str, &len);
116           strcpy (name3, name2);
117           strcat (name3, ".value");
118           if (result == ASN1_SUCCESS)
119             {
120               len = sizeof (str2);
121               result =
122                 asn1_read_value (cert_def,
123                                  "PKIX1Implicit88.id-at-countryName", str2,
124                                  &len);
125               if (!strcmp (str, str2))
126                 {
127                   asn1_create_element (cert_def,
128                                        "PKIX1Implicit88.X520OrganizationName",
129                                        &value);
130                   len = sizeof (str) - 1;
131                   asn1_read_value (cert, name3, str, &len);
132                   result =
133                     asn1_der_decoding (&value, str, len, errorDescription);
134
135                   len = sizeof (str) - 1;
136                   asn1_read_value (value, "", str, &len);       /* CHOICE */
137
138                   strcpy (name3, str);
139
140                   len = sizeof (str) - 1;
141                   asn1_read_value (value, name3, str, &len);
142                   str[len] = 0;
143                   strcat (answer, " C=");
144                   strcat (answer, str);
145
146                   asn1_delete_structure (&value);
147                 }
148               else
149                 {
150                   len = sizeof (str2);
151                   result =
152                     asn1_read_value (cert_def,
153                                      "PKIX1Implicit88.id-at-organizationName",
154                                      str2, &len);
155                   if (!strcmp (str, str2))
156                     {
157                       asn1_create_element (cert_def,
158                                            "PKIX1Implicit88.X520OrganizationName",
159                                            &value);
160
161                       len = sizeof (str) - 1;
162                       asn1_read_value (cert, name3, str, &len);
163                       asn1_der_decoding (&value, str, len, errorDescription);
164                       len = sizeof (str) - 1;
165                       asn1_read_value (value, "", str, &len);   /* CHOICE */
166                       strcpy (name3, str);
167                       len = sizeof (str) - 1;
168                       asn1_read_value (value, name3, str, &len);
169                       str[len] = 0;
170                       strcat (answer, " O=");
171                       strcat (answer, str);
172                       asn1_delete_structure (&value);
173                     }
174                   else
175                     {
176                       len = sizeof (str2);
177                       result =
178                         asn1_read_value (cert_def,
179                                          "PKIX1Implicit88.id-at-organizationalUnitName",
180                                          str2, &len);
181                       if (!strcmp (str, str2))
182                         {
183                           asn1_create_element (cert_def,
184                                                "PKIX1Implicit88.X520OrganizationalUnitName",
185                                                &value);
186                           len = sizeof (str) - 1;
187                           asn1_read_value (cert, name3, str, &len);
188                           asn1_der_decoding (&value, str, len,
189                                              errorDescription);
190                           len = sizeof (str) - 1;
191                           asn1_read_value (value, "", str, &len);       /* CHOICE */
192                           strcpy (name3, str);
193                           len = sizeof (str) - 1;
194                           asn1_read_value (value, name3, str, &len);
195                           str[len] = 0;
196                           strcat (answer, " OU=");
197                           strcat (answer, str);
198                           asn1_delete_structure (&value);
199                         }
200                     }
201                 }
202             }
203           k2++;
204         }
205       while (1);
206       k++;
207     }
208   while (1);
209 }
210
211
212 /******************************************************/
213 /* Function : create_certificate                      */
214 /* Description: creates a certificate named           */
215 /*              "certificate1". Values are the same   */
216 /*              as in rfc2459 Appendix D.1            */
217 /* Parameters:                                        */
218 /*   unsigned char *der: contains the der encoding    */
219 /*   int *der_len: number of bytes of der string      */
220 /******************************************************/
221 static void
222 create_CRL (ASN1_TYPE cert_def, unsigned char *der, int *der_len)
223 {
224   int result, k, len;
225   unsigned char str[1024];
226   const unsigned char *str2;
227   ASN1_TYPE crl = ASN1_TYPE_EMPTY;
228   ASN1_TYPE value = ASN1_TYPE_EMPTY;
229   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
230   int max_len;
231
232   max_len = *der_len;
233
234   result =
235     asn1_create_element (cert_def, "PKIX1Implicit88.CertificateList", &crl);
236
237   /* Use the next 3 lines to visit the empty certificate */
238   /*  printf("-----------------\n");
239      asn1_visit_tree(crl,"");
240      printf("-----------------\n"); */
241
242
243   /* version: v2(1) */
244   result = asn1_write_value (crl, "tbsCertList.version", "v2", 0);
245
246
247   /* signature: dsa-with-sha */
248   len = sizeof (str) - 1;
249   result =
250     asn1_read_value (cert_def, "PKIX1Implicit88.id-dsa-with-sha1", str, &len);
251   result = asn1_write_value (crl, "tbsCertList.signature.algorithm", str, 1);
252   result =
253     asn1_write_value (crl, "tbsCertList.signature.parameters", NULL, 0);
254
255
256   /* issuer: Country="US" Organization="gov" OrganizationUnit="nist" */
257   result = asn1_write_value (crl, "tbsCertList.issuer", "rdnSequence", 1);
258
259   result = asn1_write_value (crl, "tbsCertList.issuer.rdnSequence", "NEW", 1);
260   result =
261     asn1_write_value (crl, "tbsCertList.issuer.rdnSequence.?LAST", "NEW", 1);
262   /* C */
263   len = sizeof (str) - 1;
264   result =
265     asn1_read_value (cert_def, "PKIX1Implicit88.id-at-countryName", str,
266                      &len);
267   result =
268     asn1_write_value (crl, "tbsCertList.issuer.rdnSequence.?LAST.?LAST.type",
269                       str, 1);
270   result =
271     asn1_create_element (cert_def, "PKIX1Implicit88.X520countryName", &value);
272   result = asn1_write_value (value, "", "US", 2);
273   *der_len = max_len;
274   result = asn1_der_coding (value, "", der, der_len, errorDescription);
275
276   asn1_delete_structure (&value);
277   result =
278     asn1_write_value (crl, "tbsCertList.issuer.rdnSequence.?LAST.?LAST.value",
279                       der, *der_len);
280
281
282   result = asn1_write_value (crl, "tbsCertList.issuer.rdnSequence", "NEW", 4);
283   result =
284     asn1_write_value (crl, "tbsCertList.issuer.rdnSequence.?LAST", "NEW", 4);
285   /* O */
286   len = sizeof (str) - 1;
287   result =
288     asn1_read_value (cert_def, "PKIX1Implicit88.id-at-organizationName", str,
289                      &len);
290   result =
291     asn1_write_value (crl, "tbsCertList.issuer.rdnSequence.?LAST.?LAST.type",
292                       str, 8);
293   result =
294     asn1_create_element (cert_def, "PKIX1Implicit88.X520OrganizationName",
295                          &value);
296   result = asn1_write_value (value, "", "printableString", 1);
297   result = asn1_write_value (value, "printableString", "gov", 3);
298   *der_len = max_len;
299   result = asn1_der_coding (value, "", der, der_len, errorDescription);
300   asn1_delete_structure (&value);
301   result =
302     asn1_write_value (crl, "tbsCertList.issuer.rdnSequence.?LAST.?LAST.value",
303                       der, *der_len);
304
305
306   result = asn1_write_value (crl, "tbsCertList.issuer.rdnSequence", "NEW", 1);
307   result =
308     asn1_write_value (crl, "tbsCertList.issuer.rdnSequence.?LAST", "NEW", 1);
309   /* OU */
310   len = sizeof (str) - 1;
311   result =
312     asn1_read_value (cert_def, "PKIX1Implicit88.id-at-organizationalUnitName",
313                      str, &len);
314   result =
315     asn1_write_value (crl, "tbsCertList.issuer.rdnSequence.?LAST.?LAST.type",
316                       str, 1);
317   result =
318     asn1_create_element (cert_def,
319                          "PKIX1Implicit88.X520OrganizationalUnitName",
320                          &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 =
327     asn1_write_value (crl, "tbsCertList.issuer.rdnSequence.?LAST.?LAST.value",
328                       der, *der_len);
329
330
331   /* validity */
332   result = asn1_write_value (crl, "tbsCertList.thisUpdate", "utcTime", 1);
333   result =
334     asn1_write_value (crl, "tbsCertList.thisUpdate.utcTime", "970801000000Z",
335                       1);
336
337   result = asn1_write_value (crl, "tbsCertList.nextUpdate", "utcTime", 1);
338   result =
339     asn1_write_value (crl, "tbsCertList.nextUpdate.utcTime", "970808000000Z",
340                       1);
341
342
343   /* revokedCertificates */
344   result =
345     asn1_write_value (crl, "tbsCertList.revokedCertificates", "NEW", 1);
346   str[0] = 18;
347   result =
348     asn1_write_value (crl,
349                       "tbsCertList.revokedCertificates.?LAST.userCertificate",
350                       str, 1);
351   result =
352     asn1_write_value (crl,
353                       "tbsCertList.revokedCertificates.?LAST.revocationDate",
354                       "utcTime", 1);
355   result =
356     asn1_write_value (crl,
357                       "tbsCertList.revokedCertificates.?LAST.revocationDate.utcTime",
358                       "970731000000Z", 1);
359
360   result =
361     asn1_write_value (crl,
362                       "tbsCertList.revokedCertificates.?LAST.crlEntryExtensions",
363                       "NEW", 1);
364   len = sizeof (str) - 1;
365   result = asn1_read_value (cert_def, "PKIX1Implicit88.id-ce-cRLReasons",
366                             str, &len);
367   result = asn1_write_value (crl, "tbsCertList.revokedCertificates.?LAST.crlEntryExtensions.?LAST.extnID", str, 1);     /* reasonCode */
368   result =
369     asn1_write_value (crl,
370                       "tbsCertList.revokedCertificates.?LAST.crlEntryExtensions.?LAST.critical",
371                       "FALSE", 1);
372   str2 = (const unsigned char *) "\x0a\x01\x01";
373   result =
374     asn1_write_value (crl,
375                       "tbsCertList.revokedCertificates.?LAST.crlEntryExtensions.?LAST.extnValue",
376                       str2, 3);
377
378
379   /* crlExtensions */
380   result = asn1_write_value (crl, "tbsCertList.crlExtensions", NULL, 0);
381
382
383   /* signatureAlgorithm: dsa-with-sha  */
384   len = sizeof (str) - 1;
385   result =
386     asn1_read_value (cert_def, "PKIX1Implicit88.id-dsa-with-sha1", str, &len);
387   result = asn1_write_value (crl, "signatureAlgorithm.algorithm", str, 1);
388   result = asn1_write_value (crl, "signatureAlgorithm.parameters", NULL, 0);    /* NO OPTION */
389
390   /* signature */
391   *der_len = max_len;
392   result =
393     asn1_der_coding (crl, "tbsCertList", der, der_len, errorDescription);
394   if (result != ASN1_SUCCESS)
395     {
396       printf ("\n'tbsCertList' encoding creation: ERROR\n");
397       return;
398     }
399
400   /* add the lines for the signature on der[0]..der[der_len-1]: result in str2 */
401   result = asn1_write_value (crl, "signature", str2, 46 * 8);
402
403
404   /* Use the next 3 lines to visit the certificate */
405   /* printf("-----------------\n");
406      asn1_visit_tree(crl,"");
407      printf("-----------------\n"); */
408
409   *der_len = max_len;
410   result = asn1_der_coding (crl, "", der, der_len, errorDescription);
411   if (result != ASN1_SUCCESS)
412     {
413       printf ("\n'crl1' encoding creation: ERROR\n");
414       return;
415     }
416
417   /* Print the 'Certificate1' DER encoding */
418   printf ("-----------------\nCrl1 Encoding:\nNumber of bytes=%i\n",
419           *der_len);
420   for (k = 0; k < *der_len; k++)
421     printf ("%02x ", der[k]);
422   printf ("\n-----------------\n");
423
424   /* Clear the "certificate1" structure */
425   asn1_delete_structure (&crl);
426 }
427
428
429
430 /******************************************************/
431 /* Function : get_certificate                         */
432 /* Description: creates a certificate named           */
433 /*              "certificate2" from a der encoding    */
434 /*              string                                */
435 /* Parameters:                                        */
436 /*   unsigned char *der: the encoding string          */
437 /*   int der_len: number of bytes of der string      */
438 /******************************************************/
439 static void
440 get_CRL (ASN1_TYPE cert_def, unsigned char *der, int der_len)
441 {
442   int result, len, start, end;
443   unsigned char str[1024], str2[1024];
444   ASN1_TYPE crl2 = ASN1_TYPE_EMPTY;
445   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
446
447
448   asn1_create_element (cert_def, "PKIX1Implicit88.CertificateList", &crl2);
449
450   result = asn1_der_decoding (&crl2, der, der_len, errorDescription);
451
452   if (result != ASN1_SUCCESS)
453     {
454       printf ("Problems with DER encoding\n");
455       return;
456     }
457
458
459   /* issuer */
460   get_Name_type (cert_def, crl2, "tbsCertList.issuer", str);
461   printf ("crl2:\nissuer: %s\n", str);
462
463
464   /* Verify sign */
465   len = sizeof (str) - 1;
466   result = asn1_read_value (crl2, "signatureAlgorithm.algorithm", str, &len);
467
468   result =
469     asn1_read_value (cert_def, "PKIX1Implicit88.id-dsa-with-sha1", str2,
470                      &len);
471   if (!strcmp ((char *) str, (char *) str2))
472     {                           /* dsa-with-sha */
473
474       result = asn1_der_decoding_startEnd (crl2, der, der_len,
475                                            "tbsCertList", &start, &end);
476
477       /* add the lines to calculate the sha on der[start]..der[end] */
478
479       result = asn1_read_value (crl2, "signature", str, &len);
480
481       /* compare the previous value to signature ( with issuer public key) */
482     }
483
484   /* Use the next 3 lines to visit the certificate */
485   /* printf("-----------------\n");
486      asn1_visit_tree(crl2,"");
487      printf("-----------------\n"); */
488
489
490   /* Clear the "crl2" structure */
491   asn1_delete_structure (&crl2);
492 }
493
494 extern const ASN1_ARRAY_TYPE pkix_asn1_tab[];
495
496 /********************************************************/
497 /* Function : main                                      */
498 /* Description: reads the certificate description.      */
499 /*              Creates a certificate and calculate     */
500 /*              the der encoding. After that creates    */
501 /*              another certificate from der string     */
502 /********************************************************/
503 int
504 main (int argc, char *argv[])
505 {
506   int result, der_len;
507   unsigned char der[1024];
508   ASN1_TYPE PKIX1Implicit88 = ASN1_TYPE_EMPTY;
509   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
510
511   if (1)
512     result =
513       asn1_array2tree (pkix_asn1_tab, &PKIX1Implicit88, errorDescription);
514   else
515     result =
516       asn1_parser2tree ("pkix.asn", &PKIX1Implicit88, errorDescription);
517
518   if (result != ASN1_SUCCESS)
519     {
520       asn1_perror (result);
521       printf ("%s\n", errorDescription);
522       exit (1);
523     }
524
525   /* Use the following 3 lines to visit the PKIX1Implicit structures */
526   /* printf("-----------------\n");
527      asn1_visit_tree(cert_def,"PKIX1Implicit88");
528      printf("-----------------\n"); */
529
530   der_len = 1024;
531   create_CRL (PKIX1Implicit88, der, &der_len);
532
533
534   get_CRL (PKIX1Implicit88, der, der_len);
535
536   /* Clear the "PKIX1Implicit88" structures */
537   asn1_delete_structure (&PKIX1Implicit88);
538
539   return 0;
540 }