Annotation of embedaddon/axTLS/ssl/x509.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 2007, Cameron Rich
        !             3:  * 
        !             4:  * All rights reserved.
        !             5:  * 
        !             6:  * Redistribution and use in source and binary forms, with or without 
        !             7:  * modification, are permitted provided that the following conditions are met:
        !             8:  *
        !             9:  * * Redistributions of source code must retain the above copyright notice, 
        !            10:  *   this list of conditions and the following disclaimer.
        !            11:  * * Redistributions in binary form must reproduce the above copyright notice, 
        !            12:  *   this list of conditions and the following disclaimer in the documentation 
        !            13:  *   and/or other materials provided with the distribution.
        !            14:  * * Neither the name of the axTLS project nor the names of its contributors 
        !            15:  *   may be used to endorse or promote products derived from this software 
        !            16:  *   without specific prior written permission.
        !            17:  *
        !            18:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
        !            19:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
        !            20:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
        !            21:  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
        !            22:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
        !            23:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
        !            24:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
        !            25:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
        !            26:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
        !            27:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
        !            28:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            29:  */
        !            30: 
        !            31: /**
        !            32:  * @file x509.c
        !            33:  * 
        !            34:  * Certificate processing.
        !            35:  */
        !            36: 
        !            37: #include <stdio.h>
        !            38: #include <stdlib.h>
        !            39: #include <string.h>
        !            40: #include <time.h>
        !            41: #include "os_port.h"
        !            42: #include "crypto_misc.h"
        !            43: 
        !            44: #ifdef CONFIG_SSL_CERT_VERIFICATION
        !            45: /**
        !            46:  * Retrieve the signature from a certificate.
        !            47:  */
        !            48: static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len)
        !            49: {
        !            50:     int offset = 0;
        !            51:     const uint8_t *ptr = NULL;
        !            52: 
        !            53:     if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 || 
        !            54:             asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
        !            55:         goto end_get_sig;
        !            56: 
        !            57:     if (asn1_sig[offset++] != ASN1_OCTET_STRING)
        !            58:         goto end_get_sig;
        !            59:     *len = get_asn1_length(asn1_sig, &offset);
        !            60:     ptr = &asn1_sig[offset];          /* all ok */
        !            61: 
        !            62: end_get_sig:
        !            63:     return ptr;
        !            64: }
        !            65: 
        !            66: #endif
        !            67: 
        !            68: /**
        !            69:  * Construct a new x509 object.
        !            70:  * @return 0 if ok. < 0 if there was a problem.
        !            71:  */
        !            72: int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
        !            73: {
        !            74:     int begin_tbs, end_tbs;
        !            75:     int ret = X509_NOT_OK, offset = 0, cert_size = 0;
        !            76:     X509_CTX *x509_ctx;
        !            77:     BI_CTX *bi_ctx;
        !            78: 
        !            79:     *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
        !            80:     x509_ctx = *ctx;
        !            81: 
        !            82:     /* get the certificate size */
        !            83:     asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE); 
        !            84: 
        !            85:     if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        !            86:         goto end_cert;
        !            87: 
        !            88:     begin_tbs = offset;         /* start of the tbs */
        !            89:     end_tbs = begin_tbs;        /* work out the end of the tbs */
        !            90:     asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);
        !            91: 
        !            92:     if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        !            93:         goto end_cert;
        !            94: 
        !            95:     if (cert[offset] == ASN1_EXPLICIT_TAG)   /* optional version */
        !            96:     {
        !            97:         if (asn1_version(cert, &offset, x509_ctx))
        !            98:             goto end_cert;
        !            99:     }
        !           100: 
        !           101:     if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ 
        !           102:             asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        !           103:         goto end_cert;
        !           104: 
        !           105:     /* make sure the signature is ok */
        !           106:     if (asn1_signature_type(cert, &offset, x509_ctx))
        !           107:     {
        !           108:         ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
        !           109:         goto end_cert;
        !           110:     }
        !           111: 
        !           112:     if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || 
        !           113:             asn1_validity(cert, &offset, x509_ctx) ||
        !           114:             asn1_name(cert, &offset, x509_ctx->cert_dn) ||
        !           115:             asn1_public_key(cert, &offset, x509_ctx))
        !           116:     {
        !           117:         goto end_cert;
        !           118:     }
        !           119: 
        !           120:     bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
        !           121: 
        !           122: #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
        !           123:     /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
        !           124:     if (x509_ctx->sig_type == SIG_TYPE_MD5)
        !           125:     {
        !           126:         MD5_CTX md5_ctx;
        !           127:         uint8_t md5_dgst[MD5_SIZE];
        !           128:         MD5_Init(&md5_ctx);
        !           129:         MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
        !           130:         MD5_Final(md5_dgst, &md5_ctx);
        !           131:         x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
        !           132:     }
        !           133:     else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
        !           134:     {
        !           135:         SHA1_CTX sha_ctx;
        !           136:         uint8_t sha_dgst[SHA1_SIZE];
        !           137:         SHA1_Init(&sha_ctx);
        !           138:         SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
        !           139:         SHA1_Final(sha_dgst, &sha_ctx);
        !           140:         x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
        !           141:     }
        !           142:     else if (x509_ctx->sig_type == SIG_TYPE_MD2)
        !           143:     {
        !           144:         MD2_CTX md2_ctx;
        !           145:         uint8_t md2_dgst[MD2_SIZE];
        !           146:         MD2_Init(&md2_ctx);
        !           147:         MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
        !           148:         MD2_Final(md2_dgst, &md2_ctx);
        !           149:         x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE);
        !           150:     }
        !           151: 
        !           152:     if (cert[offset] == ASN1_V3_DATA)
        !           153:     {
        !           154:         int suboffset;
        !           155: 
        !           156:         ++offset;
        !           157:         get_asn1_length(cert, &offset);
        !           158: 
        !           159:         if ((suboffset = asn1_find_subjectaltname(cert, offset)) > 0)
        !           160:         {
        !           161:             if (asn1_next_obj(cert, &suboffset, ASN1_OCTET_STRING) > 0)
        !           162:             {
        !           163:                 int altlen;
        !           164: 
        !           165:                 if ((altlen = asn1_next_obj(cert, 
        !           166:                                             &suboffset, ASN1_SEQUENCE)) > 0)
        !           167:                 {
        !           168:                     int endalt = suboffset + altlen;
        !           169:                     int totalnames = 0;
        !           170: 
        !           171:                     while (suboffset < endalt)
        !           172:                     {
        !           173:                         int type = cert[suboffset++];
        !           174:                         int dnslen = get_asn1_length(cert, &suboffset);
        !           175: 
        !           176:                         if (type == ASN1_CONTEXT_DNSNAME)
        !           177:                         {
        !           178:                             x509_ctx->subject_alt_dnsnames = (char**)
        !           179:                                     realloc(x509_ctx->subject_alt_dnsnames, 
        !           180:                                        (totalnames + 2) * sizeof(char*));
        !           181:                             x509_ctx->subject_alt_dnsnames[totalnames] = 
        !           182:                                     (char*)malloc(dnslen + 1);
        !           183:                             x509_ctx->subject_alt_dnsnames[totalnames+1] = NULL;
        !           184:                             memcpy(x509_ctx->subject_alt_dnsnames[totalnames], 
        !           185:                                     cert + suboffset, dnslen);
        !           186:                             x509_ctx->subject_alt_dnsnames[
        !           187:                                     totalnames][dnslen] = 0;
        !           188:                             ++totalnames;
        !           189:                         }
        !           190: 
        !           191:                         suboffset += dnslen;
        !           192:                     }
        !           193:                 }
        !           194:             }
        !           195:         }
        !           196:     }
        !           197: 
        !           198:     offset = end_tbs;   /* skip the rest of v3 data */
        !           199:     if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || 
        !           200:             asn1_signature(cert, &offset, x509_ctx))
        !           201:         goto end_cert;
        !           202: #endif
        !           203:     ret = X509_OK;
        !           204: end_cert:
        !           205:     if (len)
        !           206:     {
        !           207:         *len = cert_size;
        !           208:     }
        !           209: 
        !           210:     if (ret)
        !           211:     {
        !           212: #ifdef CONFIG_SSL_FULL_MODE
        !           213:         printf("Error: Invalid X509 ASN.1 file (%s)\n",
        !           214:                         x509_display_error(ret));
        !           215: #endif
        !           216:         x509_free(x509_ctx);
        !           217:         *ctx = NULL;
        !           218:     }
        !           219: 
        !           220:     return ret;
        !           221: }
        !           222: 
        !           223: /**
        !           224:  * Free an X.509 object's resources.
        !           225:  */
        !           226: void x509_free(X509_CTX *x509_ctx)
        !           227: {
        !           228:     X509_CTX *next;
        !           229:     int i;
        !           230: 
        !           231:     if (x509_ctx == NULL)       /* if already null, then don't bother */
        !           232:         return;
        !           233: 
        !           234:     for (i = 0; i < X509_NUM_DN_TYPES; i++)
        !           235:     {
        !           236:         free(x509_ctx->ca_cert_dn[i]);
        !           237:         free(x509_ctx->cert_dn[i]);
        !           238:     }
        !           239: 
        !           240:     free(x509_ctx->signature);
        !           241: 
        !           242: #ifdef CONFIG_SSL_CERT_VERIFICATION 
        !           243:     if (x509_ctx->digest)
        !           244:     {
        !           245:         bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
        !           246:     }
        !           247: 
        !           248:     if (x509_ctx->subject_alt_dnsnames)
        !           249:     {
        !           250:         for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i)
        !           251:             free(x509_ctx->subject_alt_dnsnames[i]);
        !           252: 
        !           253:         free(x509_ctx->subject_alt_dnsnames);
        !           254:     }
        !           255: #endif
        !           256: 
        !           257:     RSA_free(x509_ctx->rsa_ctx);
        !           258:     next = x509_ctx->next;
        !           259:     free(x509_ctx);
        !           260:     x509_free(next);        /* clear the chain */
        !           261: }
        !           262: 
        !           263: #ifdef CONFIG_SSL_CERT_VERIFICATION
        !           264: /**
        !           265:  * Take a signature and decrypt it.
        !           266:  */
        !           267: static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
        !           268:         bigint *modulus, bigint *pub_exp)
        !           269: {
        !           270:     int i, size;
        !           271:     bigint *decrypted_bi, *dat_bi;
        !           272:     bigint *bir = NULL;
        !           273:     uint8_t *block = (uint8_t *)alloca(sig_len);
        !           274: 
        !           275:     /* decrypt */
        !           276:     dat_bi = bi_import(ctx, sig, sig_len);
        !           277:     ctx->mod_offset = BIGINT_M_OFFSET;
        !           278: 
        !           279:     /* convert to a normal block */
        !           280:     decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp);
        !           281: 
        !           282:     bi_export(ctx, decrypted_bi, block, sig_len);
        !           283:     ctx->mod_offset = BIGINT_M_OFFSET;
        !           284: 
        !           285:     i = 10; /* start at the first possible non-padded byte */
        !           286:     while (block[i++] && i < sig_len);
        !           287:     size = sig_len - i;
        !           288: 
        !           289:     /* get only the bit we want */
        !           290:     if (size > 0)
        !           291:     {
        !           292:         int len;
        !           293:         const uint8_t *sig_ptr = get_signature(&block[i], &len);
        !           294: 
        !           295:         if (sig_ptr)
        !           296:         {
        !           297:             bir = bi_import(ctx, sig_ptr, len);
        !           298:         }
        !           299:     }
        !           300: 
        !           301:     /* save a few bytes of memory */
        !           302:     bi_clear_cache(ctx);
        !           303:     return bir;
        !           304: }
        !           305: 
        !           306: /**
        !           307:  * Do some basic checks on the certificate chain.
        !           308:  *
        !           309:  * Certificate verification consists of a number of checks:
        !           310:  * - The date of the certificate is after the start date.
        !           311:  * - The date of the certificate is before the finish date.
        !           312:  * - A root certificate exists in the certificate store.
        !           313:  * - That the certificate(s) are not self-signed.
        !           314:  * - The certificate chain is valid.
        !           315:  * - The signature of the certificate is valid.
        !           316:  */
        !           317: int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) 
        !           318: {
        !           319:     int ret = X509_OK, i = 0;
        !           320:     bigint *cert_sig;
        !           321:     X509_CTX *next_cert = NULL;
        !           322:     BI_CTX *ctx = NULL;
        !           323:     bigint *mod = NULL, *expn = NULL;
        !           324:     int match_ca_cert = 0;
        !           325:     struct timeval tv;
        !           326:     uint8_t is_self_signed = 0;
        !           327: 
        !           328:     if (cert == NULL)
        !           329:     {
        !           330:         ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
        !           331:         goto end_verify;
        !           332:     }
        !           333: 
        !           334:     /* a self-signed certificate that is not in the CA store - use this 
        !           335:        to check the signature */
        !           336:     if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
        !           337:     {
        !           338:         is_self_signed = 1;
        !           339:         ctx = cert->rsa_ctx->bi_ctx;
        !           340:         mod = cert->rsa_ctx->m;
        !           341:         expn = cert->rsa_ctx->e;
        !           342:     }
        !           343: 
        !           344:     gettimeofday(&tv, NULL);
        !           345: 
        !           346:     /* check the not before date */
        !           347:     if (tv.tv_sec < cert->not_before)
        !           348:     {
        !           349:         ret = X509_VFY_ERROR_NOT_YET_VALID;
        !           350:         goto end_verify;
        !           351:     }
        !           352: 
        !           353:     /* check the not after date */
        !           354:     if (tv.tv_sec > cert->not_after)
        !           355:     {
        !           356:         ret = X509_VFY_ERROR_EXPIRED;
        !           357:         goto end_verify;
        !           358:     }
        !           359: 
        !           360:     next_cert = cert->next;
        !           361: 
        !           362:     /* last cert in the chain - look for a trusted cert */
        !           363:     if (next_cert == NULL)
        !           364:     {
        !           365:        if (ca_cert_ctx != NULL) 
        !           366:        {
        !           367:             /* go thu the CA store */
        !           368:             while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
        !           369:             {
        !           370:                 if (asn1_compare_dn(cert->ca_cert_dn,
        !           371:                                             ca_cert_ctx->cert[i]->cert_dn) == 0)
        !           372:                 {
        !           373:                     /* use this CA certificate for signature verification */
        !           374:                     match_ca_cert = 1;
        !           375:                     ctx = ca_cert_ctx->cert[i]->rsa_ctx->bi_ctx;
        !           376:                     mod = ca_cert_ctx->cert[i]->rsa_ctx->m;
        !           377:                     expn = ca_cert_ctx->cert[i]->rsa_ctx->e;
        !           378:                     break;
        !           379:                 }
        !           380: 
        !           381:                 i++;
        !           382:             }
        !           383:         }
        !           384: 
        !           385:         /* couldn't find a trusted cert (& let self-signed errors 
        !           386:            be returned) */
        !           387:         if (!match_ca_cert && !is_self_signed)
        !           388:         {
        !           389:             ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
        !           390:             goto end_verify;
        !           391:         }
        !           392:     }
        !           393:     else if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0)
        !           394:     {
        !           395:         /* check the chain */
        !           396:         ret = X509_VFY_ERROR_INVALID_CHAIN;
        !           397:         goto end_verify;
        !           398:     }
        !           399:     else /* use the next certificate in the chain for signature verify */
        !           400:     {
        !           401:         ctx = next_cert->rsa_ctx->bi_ctx;
        !           402:         mod = next_cert->rsa_ctx->m;
        !           403:         expn = next_cert->rsa_ctx->e;
        !           404:     }
        !           405: 
        !           406:     /* cert is self signed */
        !           407:     if (!match_ca_cert && is_self_signed)
        !           408:     {
        !           409:         ret = X509_VFY_ERROR_SELF_SIGNED;
        !           410:         goto end_verify;
        !           411:     }
        !           412: 
        !           413:     /* check the signature */
        !           414:     cert_sig = sig_verify(ctx, cert->signature, cert->sig_len, 
        !           415:                         bi_clone(ctx, mod), bi_clone(ctx, expn));
        !           416: 
        !           417:     if (cert_sig && cert->digest)
        !           418:     {
        !           419:         if (bi_compare(cert_sig, cert->digest) != 0)
        !           420:             ret = X509_VFY_ERROR_BAD_SIGNATURE;
        !           421: 
        !           422: 
        !           423:         bi_free(ctx, cert_sig);
        !           424:     }
        !           425:     else
        !           426:     {
        !           427:         ret = X509_VFY_ERROR_BAD_SIGNATURE;
        !           428:     }
        !           429: 
        !           430:     if (ret)
        !           431:         goto end_verify;
        !           432: 
        !           433:     /* go down the certificate chain using recursion. */
        !           434:     if (next_cert != NULL)
        !           435:     {
        !           436:         ret = x509_verify(ca_cert_ctx, next_cert);
        !           437:     }
        !           438: 
        !           439: end_verify:
        !           440:     return ret;
        !           441: }
        !           442: #endif
        !           443: 
        !           444: #if defined (CONFIG_SSL_FULL_MODE)
        !           445: /**
        !           446:  * Used for diagnostics.
        !           447:  */
        !           448: static const char *not_part_of_cert = "<Not Part Of Certificate>";
        !           449: void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx) 
        !           450: {
        !           451:     if (cert == NULL)
        !           452:         return;
        !           453: 
        !           454:     printf("=== CERTIFICATE ISSUED TO ===\n");
        !           455:     printf("Common Name (CN):\t\t");
        !           456:     printf("%s\n", cert->cert_dn[X509_COMMON_NAME] ?
        !           457:                     cert->cert_dn[X509_COMMON_NAME] : not_part_of_cert);
        !           458: 
        !           459:     printf("Organization (O):\t\t");
        !           460:     printf("%s\n", cert->cert_dn[X509_ORGANIZATION] ?
        !           461:         cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert);
        !           462: 
        !           463:     printf("Organizational Unit (OU):\t");
        !           464:     printf("%s\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT] ?
        !           465:         cert->cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
        !           466: 
        !           467:     printf("=== CERTIFICATE ISSUED BY ===\n");
        !           468:     printf("Common Name (CN):\t\t");
        !           469:     printf("%s\n", cert->ca_cert_dn[X509_COMMON_NAME] ?
        !           470:                     cert->ca_cert_dn[X509_COMMON_NAME] : not_part_of_cert);
        !           471: 
        !           472:     printf("Organization (O):\t\t");
        !           473:     printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATION] ?
        !           474:         cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert);
        !           475: 
        !           476:     printf("Organizational Unit (OU):\t");
        !           477:     printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] ?
        !           478:         cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
        !           479: 
        !           480:     printf("Not Before:\t\t\t%s", ctime(&cert->not_before));
        !           481:     printf("Not After:\t\t\t%s", ctime(&cert->not_after));
        !           482:     printf("RSA bitsize:\t\t\t%d\n", cert->rsa_ctx->num_octets*8);
        !           483:     printf("Sig Type:\t\t\t");
        !           484:     switch (cert->sig_type)
        !           485:     {
        !           486:         case SIG_TYPE_MD5:
        !           487:             printf("MD5\n");
        !           488:             break;
        !           489:         case SIG_TYPE_SHA1:
        !           490:             printf("SHA1\n");
        !           491:             break;
        !           492:         case SIG_TYPE_MD2:
        !           493:             printf("MD2\n");
        !           494:             break;
        !           495:         default:
        !           496:             printf("Unrecognized: %d\n", cert->sig_type);
        !           497:             break;
        !           498:     }
        !           499: 
        !           500:     if (ca_cert_ctx)
        !           501:     {
        !           502:         printf("Verify:\t\t\t\t%s\n",
        !           503:                 x509_display_error(x509_verify(ca_cert_ctx, cert)));
        !           504:     }
        !           505: 
        !           506: #if 0
        !           507:     print_blob("Signature", cert->signature, cert->sig_len);
        !           508:     bi_print("Modulus", cert->rsa_ctx->m);
        !           509:     bi_print("Pub Exp", cert->rsa_ctx->e);
        !           510: #endif
        !           511: 
        !           512:     if (ca_cert_ctx)
        !           513:     {
        !           514:         x509_print(cert->next, ca_cert_ctx);
        !           515:     }
        !           516: 
        !           517:     TTY_FLUSH();
        !           518: }
        !           519: 
        !           520: const char * x509_display_error(int error)
        !           521: {
        !           522:     switch (error)
        !           523:     {
        !           524:         case X509_OK:
        !           525:             return "Certificate verify successful";
        !           526: 
        !           527:         case X509_NOT_OK:
        !           528:             return "X509 not ok";
        !           529: 
        !           530:         case X509_VFY_ERROR_NO_TRUSTED_CERT:
        !           531:             return "No trusted cert is available";
        !           532: 
        !           533:         case X509_VFY_ERROR_BAD_SIGNATURE:
        !           534:             return "Bad signature";
        !           535: 
        !           536:         case X509_VFY_ERROR_NOT_YET_VALID:
        !           537:             return "Cert is not yet valid";
        !           538: 
        !           539:         case X509_VFY_ERROR_EXPIRED:
        !           540:             return "Cert has expired";
        !           541: 
        !           542:         case X509_VFY_ERROR_SELF_SIGNED:
        !           543:             return "Cert is self-signed";
        !           544: 
        !           545:         case X509_VFY_ERROR_INVALID_CHAIN:
        !           546:             return "Chain is invalid (check order of certs)";
        !           547: 
        !           548:         case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
        !           549:             return "Unsupported digest";
        !           550: 
        !           551:         case X509_INVALID_PRIV_KEY:
        !           552:             return "Invalid private key";
        !           553: 
        !           554:         default:
        !           555:             return "Unknown";
        !           556:     }
        !           557: }
        !           558: #endif      /* CONFIG_SSL_FULL_MODE */
        !           559: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>