[crypto] Remove unused files
[people/asdlkf/gpxe.git] / src / crypto / axtls / axtls_asn1.c
1 /*
2  *  Copyright(C) 2006 Cameron Rich
3  *
4  *  This library is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU Lesser General Public License as published by
6  *  the Free Software Foundation; either version 2.1 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public License
15  *  along with this library; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 /**
20  * @file asn1.c
21  * 
22  * Some primitive asn methods for extraction rsa modulus information. It also
23  * is used for retrieving information from X.509 certificates.
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 #include "crypto.h"
31
32 #define SIG_OID_PREFIX_SIZE     8
33
34 #define SIG_TYPE_MD2            0x02
35 #define SIG_TYPE_MD5            0x04
36 #define SIG_TYPE_SHA1           0x05
37
38 /* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
39 static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] = 
40 {
41     0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
42 };
43
44 /* CN, O, OU */
45 static const uint8_t g_dn_types[] = { 3, 10, 11 };
46
47 static int get_asn1_length(const uint8_t *buf, int *offset)
48 {
49     int len, i;
50
51     if (!(buf[*offset] & 0x80)) /* short form */
52     {
53         len = buf[(*offset)++];
54     }
55     else    /* long form */
56     {
57         int length_bytes = buf[(*offset)++]&0x7f;
58         len = 0;
59         for (i = 0; i < length_bytes; i++)
60         {
61             len <<= 8;
62             len += buf[(*offset)++];
63         }
64     }
65
66     return len;
67 }
68
69 /**
70  * Skip the ASN1.1 object type and its length. Get ready to read the object's
71  * data.
72  */
73 int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
74 {
75     if (buf[*offset] != obj_type)
76         return X509_NOT_OK;
77     (*offset)++;
78     return get_asn1_length(buf, offset);
79 }
80
81 /**
82  * Skip over an ASN.1 object type completely. Get ready to read the next
83  * object.
84  */
85 int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
86 {
87     int len;
88
89     if (buf[*offset] != obj_type)
90         return X509_NOT_OK;
91     (*offset)++;
92     len = get_asn1_length(buf, offset);
93     *offset += len;
94     return 0;
95 }
96
97 /**
98  * Read an integer value for ASN.1 data
99  * Note: This function allocates memory which must be freed by the user.
100  */
101 int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
102 {
103     int len;
104
105     if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
106         goto end_int_array;
107
108     *object = (uint8_t *)malloc(len);
109     memcpy(*object, &buf[*offset], len);
110     *offset += len;
111
112 end_int_array:
113     return len;
114 }
115
116 #if 0
117
118 /**
119  * Get all the RSA private key specifics from an ASN.1 encoded file 
120  */
121 int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
122 {
123     int offset = 7;
124     uint8_t *modulus, *priv_exp, *pub_exp;
125     int mod_len, priv_len, pub_len;
126 #ifdef CONFIG_BIGINT_CRT
127     uint8_t *p, *q, *dP, *dQ, *qInv;
128     int p_len, q_len, dP_len, dQ_len, qInv_len;
129 #endif
130
131     /* not in der format */
132     if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
133     {
134 #ifdef CONFIG_SSL_FULL_MODE
135         printf("Error: This is not a valid ASN.1 file\n");
136 #endif
137         return X509_INVALID_PRIV_KEY;
138     }
139
140     /* initialise the RNG */
141     RNG_initialize(buf, len);
142
143     mod_len = asn1_get_int(buf, &offset, &modulus);
144     pub_len = asn1_get_int(buf, &offset, &pub_exp);
145     priv_len = asn1_get_int(buf, &offset, &priv_exp);
146
147     if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
148         return X509_INVALID_PRIV_KEY;
149
150 #ifdef CONFIG_BIGINT_CRT
151     p_len = asn1_get_int(buf, &offset, &p);
152     q_len = asn1_get_int(buf, &offset, &q);
153     dP_len = asn1_get_int(buf, &offset, &dP);
154     dQ_len = asn1_get_int(buf, &offset, &dQ);
155     qInv_len = asn1_get_int(buf, &offset, &qInv);
156
157     if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
158         return X509_INVALID_PRIV_KEY;
159
160     RSA_priv_key_new(rsa_ctx, 
161             modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
162             p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
163
164     free(p);
165     free(q);
166     free(dP);
167     free(dQ);
168     free(qInv);
169 #else
170     RSA_priv_key_new(rsa_ctx, 
171             modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
172 #endif
173
174     free(modulus);
175     free(priv_exp);
176     free(pub_exp);
177     return X509_OK;
178 }
179
180 /**
181  * Get the time of a certificate. Ignore hours/minutes/seconds.
182  */
183 static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
184 {
185     int ret = X509_NOT_OK, len, t_offset;
186     struct tm tm;
187
188     if (buf[(*offset)++] != ASN1_UTC_TIME)
189         goto end_utc_time;
190     len = get_asn1_length(buf, offset);
191     t_offset = *offset;
192
193     memset(&tm, 0, sizeof(struct tm));
194     tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
195
196     if (tm.tm_year <= 50)    /* 1951-2050 thing */
197     {
198         tm.tm_year += 100;
199     }
200
201     tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
202     tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
203     *t = mktime(&tm);
204     *offset += len;
205     ret = X509_OK;
206
207 end_utc_time:
208     return ret;
209 }
210
211 /**
212  * Get the version type of a certificate (which we don't actually care about)
213  */
214 static int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
215 {
216     int ret = X509_NOT_OK;
217
218     (*offset) += 2;        /* get past explicit tag */
219     if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
220         goto end_version;
221
222     ret = X509_OK;
223 end_version:
224     return ret;
225 }
226
227 /**
228  * Retrieve the notbefore and notafter certificate times.
229  */
230 static int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
231 {
232     return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
233               asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
234               asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
235 }
236
237 /**
238  * Get the components of a distinguished name 
239  */
240 static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
241 {
242     int dn_type = 0;
243     int len;
244
245     if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
246         goto end_oid;
247
248     /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name 
249        components we are interested in. */
250     if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
251         dn_type = buf[(*offset)++];
252     else
253     {
254         *offset += len;     /* skip over it */
255     }
256
257 end_oid:
258     return dn_type;
259 }
260
261 /**
262  * Obtain an ASN.1 printable string type.
263  */
264 static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
265 {
266     int len = X509_NOT_OK;
267
268     /* some certs have this awful crud in them for some reason */
269     if (buf[*offset] != ASN1_PRINTABLE_STR && 
270             buf[*offset] != ASN1_TELETEX_STR && buf[*offset] != ASN1_IA5_STR)
271         goto end_pnt_str;
272
273     (*offset)++;
274     len = get_asn1_length(buf, offset);
275     *str = (char *)malloc(len+1);       /* allow for null */
276     memcpy(*str, &buf[*offset], len);
277     (*str)[len] = 0;                    /* null terminate */
278     *offset += len;
279 end_pnt_str:
280     return len;
281 }
282
283 /**
284  * Get the subject name (or the issuer) of a certificate.
285  */
286 static int asn1_name(const uint8_t *cert, int *offset, char *dn[])
287 {
288     int ret = X509_NOT_OK;
289     int dn_type;
290     char *tmp = NULL;
291
292     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
293         goto end_name;
294
295     while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
296     {
297         int i, found = 0;
298
299         if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
300                (dn_type = asn1_get_oid_x520(cert, offset)) < 0)
301             goto end_name;
302
303         if (asn1_get_printable_str(cert, offset, &tmp) < 0)
304         {
305             free(tmp);
306             goto end_name;
307         }
308
309         /* find the distinguished named type */
310         for (i = 0; i < X509_NUM_DN_TYPES; i++)
311         {
312             if (dn_type == g_dn_types[i])
313             {
314                 if (dn[i] == NULL)
315                 {
316                     dn[i] = tmp;
317                     found = 1;
318                     break;
319                 }
320             }
321         }
322
323         if (found == 0) /* not found so get rid of it */
324         {
325             free(tmp);
326         }
327     }
328
329     ret = X509_OK;
330 end_name:
331     return ret;
332 }
333
334 /**
335  * Read the modulus and public exponent of a certificate.
336  */
337 static int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
338 {
339     int ret = X509_NOT_OK, mod_len, pub_len;
340     uint8_t *modulus, *pub_exp;
341
342     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
343             asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
344             asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
345         goto end_pub_key;
346
347     (*offset)++;
348
349     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
350         goto end_pub_key;
351
352     mod_len = asn1_get_int(cert, offset, &modulus);
353     pub_len = asn1_get_int(cert, offset, &pub_exp);
354
355     RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
356
357     free(modulus);
358     free(pub_exp);
359     ret = X509_OK;
360
361 end_pub_key:
362     return ret;
363 }
364
365 #ifdef CONFIG_SSL_CERT_VERIFICATION
366 /**
367  * Read the signature of the certificate.
368  */
369 static int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
370 {
371     int ret = X509_NOT_OK;
372
373     if (cert[(*offset)++] != ASN1_BIT_STRING)
374         goto end_sig;
375
376     x509_ctx->sig_len = get_asn1_length(cert, offset);
377     x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
378     memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
379     *offset += x509_ctx->sig_len;
380     ret = X509_OK;
381
382 end_sig:
383     return ret;
384 }
385
386 /*
387  * Compare 2 distinguished name components for equality 
388  * @return 0 if a match
389  */
390 static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
391 {
392     int ret = 1;
393
394     if ((dn1 && dn2 == NULL) || (dn1 == NULL && dn2)) goto err_no_match;
395
396     ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 0;
397
398 err_no_match:
399     return ret;
400 }
401
402 /**
403  * Clean up all of the CA certificates.
404  */
405 void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
406 {
407     int i = 0;
408
409     while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
410     {
411         x509_free(ca_cert_ctx->cert[i]);
412         ca_cert_ctx->cert[i++] = NULL;
413     }
414
415     free(ca_cert_ctx);
416 }
417
418 /*
419  * Compare 2 distinguished names for equality 
420  * @return 0 if a match
421  */
422 static int asn1_compare_dn(char * const dn1[], char * const dn2[])
423 {
424     int i;
425
426     for (i = 0; i < X509_NUM_DN_TYPES; i++)
427     {
428         if (asn1_compare_dn_comp(dn1[i], dn2[i]))
429         {
430             return 1;
431         }
432     }
433
434     return 0;       /* all good */
435 }
436
437 /**
438  * Retrieve the signature from a certificate.
439  */
440 const uint8_t *x509_get_signature(const uint8_t *asn1_sig, int *len)
441 {
442     int offset = 0;
443     const uint8_t *ptr = NULL;
444
445     if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 || 
446             asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
447         goto end_get_sig;
448
449     if (asn1_sig[offset++] != ASN1_OCTET_STRING)
450         goto end_get_sig;
451     *len = get_asn1_length(asn1_sig, &offset);
452     ptr = &asn1_sig[offset];          /* all ok */
453
454 end_get_sig:
455     return ptr;
456 }
457
458 #endif
459
460 /**
461  * Read the signature type of the certificate. We only support RSA-MD5 and
462  * RSA-SHA1 signature types.
463  */
464 static int asn1_signature_type(const uint8_t *cert, 
465                                 int *offset, X509_CTX *x509_ctx)
466 {
467     int ret = X509_NOT_OK, len;
468
469     if (cert[(*offset)++] != ASN1_OID)
470         goto end_check_sig;
471
472     len = get_asn1_length(cert, offset);
473
474     if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
475         goto end_check_sig;     /* unrecognised cert type */
476
477     x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
478
479     *offset += len;
480     if (asn1_skip_obj(cert, offset, ASN1_NULL))
481         goto end_check_sig;
482     ret = X509_OK;
483
484 end_check_sig:
485     return ret;
486 }
487
488 /**
489  * Construct a new x509 object.
490  * @return 0 if ok. < 0 if there was a problem.
491  */
492 int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
493 {
494     int begin_tbs, end_tbs;
495     int ret = X509_NOT_OK, offset = 0, cert_size = 0;
496     X509_CTX *x509_ctx;
497     BI_CTX *bi_ctx;
498
499     *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
500     x509_ctx = *ctx;
501
502     /* get the certificate size */
503     asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE); 
504
505     if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
506         goto end_cert;
507
508     begin_tbs = offset;         /* start of the tbs */
509     end_tbs = begin_tbs;        /* work out the end of the tbs */
510     asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);
511
512     if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
513         goto end_cert;
514
515     if (cert[offset] == ASN1_EXPLICIT_TAG)   /* optional version */
516     {
517         if (asn1_version(cert, &offset, x509_ctx))
518             goto end_cert;
519     }
520
521     if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ 
522             asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
523         goto end_cert;
524
525     /* make sure the signature is ok */
526     if (asn1_signature_type(cert, &offset, x509_ctx))
527     {
528         ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
529         goto end_cert;
530     }
531
532     if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || 
533             asn1_validity(cert, &offset, x509_ctx) ||
534             asn1_name(cert, &offset, x509_ctx->cert_dn) ||
535             asn1_public_key(cert, &offset, x509_ctx))
536         goto end_cert;
537
538     bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
539
540 #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
541     /* use the appropriate signature algorithm (either SHA1 or MD5) */
542     if (x509_ctx->sig_type == SIG_TYPE_MD5)
543     {
544         MD5_CTX md5_ctx;
545         uint8_t md5_dgst[MD5_SIZE];
546         MD5Init(&md5_ctx);
547         MD5Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
548         MD5Final(&md5_ctx, md5_dgst);
549         x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
550     }
551     else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
552     {
553         SHA1_CTX sha_ctx;
554         uint8_t sha_dgst[SHA1_SIZE];
555         SHA1Init(&sha_ctx);
556         SHA1Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
557         SHA1Final(&sha_ctx, sha_dgst);
558         x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
559     }
560
561     offset = end_tbs;   /* skip the v3 data */
562     if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || 
563             asn1_signature(cert, &offset, x509_ctx))
564         goto end_cert;
565 #endif
566
567     if (len)
568     {
569         *len = cert_size;
570     }
571
572     ret = X509_OK;
573 end_cert:
574
575 #ifdef CONFIG_SSL_FULL_MODE
576     if (ret)
577     {
578         printf("Error: Invalid X509 ASN.1 file\n");
579     }
580 #endif
581
582     return ret;
583 }
584
585 /**
586  * Free an X.509 object's resources.
587  */
588 void x509_free(X509_CTX *x509_ctx)
589 {
590     X509_CTX *next;
591     int i;
592
593     if (x509_ctx == NULL)       /* if already null, then don't bother */
594         return;
595
596     for (i = 0; i < X509_NUM_DN_TYPES; i++)
597     {
598         free(x509_ctx->ca_cert_dn[i]);
599         free(x509_ctx->cert_dn[i]);
600     }
601
602     free(x509_ctx->signature);
603
604 #ifdef CONFIG_SSL_CERT_VERIFICATION 
605     if (x509_ctx->digest)
606     {
607         bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
608     }
609 #endif
610
611     RSA_free(x509_ctx->rsa_ctx);
612
613     next = x509_ctx->next;
614     free(x509_ctx);
615     x509_free(next);        /* clear the chain */
616 }
617
618 #ifdef CONFIG_SSL_CERT_VERIFICATION
619 /**
620  * Do some basic checks on the certificate chain.
621  *
622  * Certificate verification consists of a number of checks:
623  * - A root certificate exists in the certificate store.
624  * - The date of the certificate is after the start date.
625  * - The date of the certificate is before the finish date.
626  * - The certificate chain is valid.
627  * - That the certificate(s) are not self-signed.
628  * - The signature of the certificate is valid.
629  */
630 int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) 
631 {
632     int ret = X509_OK, i = 0;
633     bigint *cert_sig;
634     X509_CTX *next_cert = NULL;
635     BI_CTX *ctx;
636     bigint *mod, *expn;
637     struct timeval tv;
638     int match_ca_cert = 0;
639
640     if (cert == NULL || ca_cert_ctx == NULL)
641     {
642         ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
643         goto end_verify;
644     }
645
646     /* last cert in the chain - look for a trusted cert */
647     if (cert->next == NULL)
648     {
649         while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
650         {
651             if (asn1_compare_dn(cert->ca_cert_dn,
652                                         ca_cert_ctx->cert[i]->cert_dn) == 0)
653             {
654                 match_ca_cert = 1;
655                 break;
656             }
657
658             i++;
659         }
660
661         if (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
662         {
663             next_cert = ca_cert_ctx->cert[i];
664         }
665         else    /* trusted cert not found */
666         {
667             ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
668             goto end_verify;
669         }
670     }
671     else
672     {
673         next_cert = cert->next;
674     }
675
676     gettimeofday(&tv, NULL);
677
678     /* check the not before date */
679     if (tv.tv_sec < cert->not_before)
680     {
681         ret = X509_VFY_ERROR_NOT_YET_VALID;
682         goto end_verify;
683     }
684
685     /* check the not after date */
686     if (tv.tv_sec > cert->not_after)
687     {
688         ret = X509_VFY_ERROR_EXPIRED;
689         goto end_verify;
690     }
691
692     /* check the chain integrity */
693     if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn))
694     {
695         ret = X509_VFY_ERROR_INVALID_CHAIN;
696         goto end_verify;
697     }
698
699     /* check for self-signing */
700     if (!match_ca_cert && asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
701     {
702         ret = X509_VFY_ERROR_SELF_SIGNED;
703         goto end_verify;
704     }
705
706     /* check the signature */
707     ctx = cert->rsa_ctx->bi_ctx;
708     mod = next_cert->rsa_ctx->m;
709     expn = next_cert->rsa_ctx->e;
710     cert_sig = RSA_sign_verify(ctx, cert->signature, cert->sig_len, 
711             bi_clone(ctx, mod), bi_clone(ctx, expn));
712
713     if (cert_sig)
714     {
715         ret = cert->digest ?    /* check the signature */
716             bi_compare(cert_sig, cert->digest) :
717             X509_VFY_ERROR_UNSUPPORTED_DIGEST;
718         bi_free(ctx, cert_sig);
719
720         if (ret)
721             goto end_verify;
722     }
723     else
724     {
725         ret = X509_VFY_ERROR_BAD_SIGNATURE;
726         goto end_verify;
727     }
728
729     /* go down the certificate chain using recursion. */
730     if (ret == 0 && cert->next)
731     {
732         ret = x509_verify(ca_cert_ctx, next_cert);
733     }
734
735 end_verify:
736     return ret;
737 }
738 #endif
739
740 #if defined (CONFIG_SSL_FULL_MODE)
741 /**
742  * Used for diagnostics.
743  */
744 void x509_print(CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) 
745 {
746     if (cert == NULL)
747         return;
748
749     printf("----------------   CERT DEBUG   ----------------\n");
750     printf("* CA Cert Distinguished Name\n");
751     if (cert->ca_cert_dn[X509_COMMON_NAME])
752     {
753         printf("Common Name (CN):\t%s\n", cert->ca_cert_dn[X509_COMMON_NAME]);
754     }
755
756     if (cert->ca_cert_dn[X509_ORGANIZATION])
757     {
758         printf("Organization (O):\t%s\n", cert->ca_cert_dn[X509_ORGANIZATION]);
759     }
760
761     if (cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE])
762     {
763         printf("Organizational Unit (OU): %s\n", 
764                 cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE]);
765     }
766
767     printf("* Cert Distinguished Name\n");
768     if (cert->cert_dn[X509_COMMON_NAME])
769     {
770         printf("Common Name (CN):\t%s\n", cert->cert_dn[X509_COMMON_NAME]);
771     }
772
773     if (cert->cert_dn[X509_ORGANIZATION])
774     {
775         printf("Organization (O):\t%s\n", cert->cert_dn[X509_ORGANIZATION]);
776     }
777
778     if (cert->cert_dn[X509_ORGANIZATIONAL_TYPE])
779     {
780         printf("Organizational Unit (OU): %s\n", 
781                 cert->cert_dn[X509_ORGANIZATIONAL_TYPE]);
782     }
783
784     printf("Not Before:\t\t%s", ctime(&cert->not_before));
785     printf("Not After:\t\t%s", ctime(&cert->not_after));
786     printf("RSA bitsize:\t\t%d\n", cert->rsa_ctx->num_octets*8);
787     printf("Sig Type:\t\t");
788     switch (cert->sig_type)
789     {
790         case SIG_TYPE_MD5:
791             printf("MD5\n");
792             break;
793         case SIG_TYPE_SHA1:
794             printf("SHA1\n");
795             break;
796         case SIG_TYPE_MD2:
797             printf("MD2\n");
798             break;
799         default:
800             printf("Unrecognized: %d\n", cert->sig_type);
801             break;
802     }
803
804     printf("Verify:\t\t\t");
805
806     if (ca_cert_ctx)
807     {
808         x509_display_error(x509_verify(ca_cert_ctx, cert));
809     }
810
811     printf("\n");
812 #if 0
813     print_blob("Signature", cert->signature, cert->sig_len);
814     bi_print("Modulus", cert->rsa_ctx->m);
815     bi_print("Pub Exp", cert->rsa_ctx->e);
816 #endif
817
818     if (ca_cert_ctx)
819     {
820         x509_print(ca_cert_ctx, cert->next);
821     }
822 }
823
824 void x509_display_error(int error)
825 {
826     switch (error)
827     {
828         case X509_NOT_OK:
829             printf("X509 not ok");
830             break;
831
832         case X509_VFY_ERROR_NO_TRUSTED_CERT:
833             printf("No trusted cert is available");
834             break;
835
836         case X509_VFY_ERROR_BAD_SIGNATURE:
837             printf("Bad signature");
838             break;
839
840         case X509_VFY_ERROR_NOT_YET_VALID:
841             printf("Cert is not yet valid");
842             break;
843
844         case X509_VFY_ERROR_EXPIRED:
845             printf("Cert has expired");
846             break;
847
848         case X509_VFY_ERROR_SELF_SIGNED:
849             printf("Cert is self-signed");
850             break;
851
852         case X509_VFY_ERROR_INVALID_CHAIN:
853             printf("Chain is invalid (check order of certs)");
854             break;
855
856         case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
857             printf("Unsupported digest");
858             break;
859
860         case X509_INVALID_PRIV_KEY:
861             printf("Invalid private key");
862             break;
863     }
864 }
865 #endif      /* CONFIG_SSL_FULL_MODE */
866
867 #endif