Annotation of embedaddon/strongswan/src/libstrongswan/plugins/x509/x509_cert.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
        !             3:  * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
        !             4:  * Copyright (C) 2002 Mario Strasser
        !             5:  * Copyright (C) 2000-2017 Andreas Steffen
        !             6:  * Copyright (C) 2006-2009 Martin Willi
        !             7:  * Copyright (C) 2008-2017 Tobias Brunner
        !             8:  * HSR Hochschule fuer Technik Rapperswil
        !             9:  *
        !            10:  * This program is free software; you can redistribute it and/or modify it
        !            11:  * under the terms of the GNU General Public License as published by the
        !            12:  * Free Software Foundation; either version 2 of the License, or (at your
        !            13:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            14:  *
        !            15:  * This program is distributed in the hope that it will be useful, but
        !            16:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            17:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            18:  * for more details.
        !            19:  */
        !            20: 
        !            21: #define _GNU_SOURCE
        !            22: 
        !            23: #include <sys/stat.h>
        !            24: #include <time.h>
        !            25: #include <unistd.h>
        !            26: #include <string.h>
        !            27: #include <stdio.h>
        !            28: 
        !            29: #include "x509_cert.h"
        !            30: 
        !            31: #include <library.h>
        !            32: #include <utils/debug.h>
        !            33: #include <asn1/oid.h>
        !            34: #include <asn1/asn1.h>
        !            35: #include <asn1/asn1_parser.h>
        !            36: #include <crypto/hashers/hasher.h>
        !            37: #include <credentials/keys/private_key.h>
        !            38: #include <collections/linked_list.h>
        !            39: #include <utils/identification.h>
        !            40: #include <selectors/traffic_selector.h>
        !            41: 
        !            42: /**
        !            43:  * Different kinds of generalNames
        !            44:  */
        !            45: typedef enum {
        !            46:        GN_OTHER_NAME =         0,
        !            47:        GN_RFC822_NAME =        1,
        !            48:        GN_DNS_NAME =           2,
        !            49:        GN_X400_ADDRESS =       3,
        !            50:        GN_DIRECTORY_NAME =     4,
        !            51:        GN_EDI_PARTY_NAME = 5,
        !            52:        GN_URI =                        6,
        !            53:        GN_IP_ADDRESS =         7,
        !            54:        GN_REGISTERED_ID =      8,
        !            55: } generalNames_t;
        !            56: 
        !            57: 
        !            58: typedef struct private_x509_cert_t private_x509_cert_t;
        !            59: 
        !            60: /**
        !            61:  * Private data of a x509_cert_t object.
        !            62:  */
        !            63: struct private_x509_cert_t {
        !            64:        /**
        !            65:         * Public interface for this certificate.
        !            66:         */
        !            67:        x509_cert_t public;
        !            68: 
        !            69:        /**
        !            70:         * X.509 certificate encoding in ASN.1 DER format
        !            71:         */
        !            72:        chunk_t encoding;
        !            73: 
        !            74:        /**
        !            75:         * SHA1 hash of the DER encoding of this X.509 certificate
        !            76:         */
        !            77:        chunk_t encoding_hash;
        !            78: 
        !            79:        /**
        !            80:         * X.509 certificate body over which signature is computed
        !            81:         */
        !            82:        chunk_t tbsCertificate;
        !            83: 
        !            84:        /**
        !            85:         * Version of the X.509 certificate
        !            86:         */
        !            87:        u_int version;
        !            88: 
        !            89:        /**
        !            90:         * Serial number of the X.509 certificate
        !            91:         */
        !            92:        chunk_t serialNumber;
        !            93: 
        !            94:        /**
        !            95:         * ID representing the certificate issuer
        !            96:         */
        !            97:        identification_t *issuer;
        !            98: 
        !            99:        /**
        !           100:         * Start time of certificate validity
        !           101:         */
        !           102:        time_t notBefore;
        !           103: 
        !           104:        /**
        !           105:         * End time of certificate validity
        !           106:         */
        !           107:        time_t notAfter;
        !           108: 
        !           109:        /**
        !           110:         * ID representing the certificate subject
        !           111:         */
        !           112:        identification_t *subject;
        !           113: 
        !           114:        /**
        !           115:         * List of subjectAltNames as identification_t
        !           116:         */
        !           117:        linked_list_t *subjectAltNames;
        !           118: 
        !           119:        /**
        !           120:         * List of crlDistributionPoints as x509_cdp_t*
        !           121:         */
        !           122:        linked_list_t *crl_uris;
        !           123: 
        !           124:        /**
        !           125:         * List of ocspAccessLocations as allocated char*
        !           126:         */
        !           127:        linked_list_t *ocsp_uris;
        !           128: 
        !           129:        /**
        !           130:         * List of ipAddrBlocks as traffic_selector_t
        !           131:         */
        !           132:        linked_list_t *ipAddrBlocks;
        !           133: 
        !           134:        /**
        !           135:         * List of permitted name constraints
        !           136:         */
        !           137:        linked_list_t *permitted_names;
        !           138: 
        !           139:        /**
        !           140:         * List of excluded name constraints
        !           141:         */
        !           142:        linked_list_t *excluded_names;
        !           143: 
        !           144:        /**
        !           145:         * List of certificatePolicies, as x509_cert_policy_t
        !           146:         */
        !           147:        linked_list_t *cert_policies;
        !           148: 
        !           149:        /**
        !           150:         * List of policyMappings, as x509_policy_mapping_t
        !           151:         */
        !           152:        linked_list_t *policy_mappings;
        !           153: 
        !           154:        /**
        !           155:         * certificate's embedded public key
        !           156:         */
        !           157:        public_key_t *public_key;
        !           158: 
        !           159:        /**
        !           160:         * Subject Key Identifier
        !           161:         */
        !           162:        chunk_t subjectKeyIdentifier;
        !           163: 
        !           164:        /**
        !           165:         * Authority Key Identifier
        !           166:         */
        !           167:        chunk_t authKeyIdentifier;
        !           168: 
        !           169:        /**
        !           170:         * Authority Key Serial Number
        !           171:         */
        !           172:        chunk_t authKeySerialNumber;
        !           173: 
        !           174:        /**
        !           175:         * Optional OID of an [unsupported] critical extension
        !           176:         */
        !           177:        chunk_t critical_extension_oid;
        !           178: 
        !           179:        /**
        !           180:         * Path Length Constraint
        !           181:         */
        !           182:        u_char pathLenConstraint;
        !           183: 
        !           184:        /**
        !           185:         * requireExplicitPolicy Constraint
        !           186:         */
        !           187:        u_char require_explicit;
        !           188: 
        !           189:        /**
        !           190:         * inhibitPolicyMapping Constraint
        !           191:         */
        !           192:        u_char inhibit_mapping;
        !           193: 
        !           194:        /**
        !           195:         * inhibitAnyPolicy Constraint
        !           196:         */
        !           197:        u_char inhibit_any;
        !           198: 
        !           199:        /**
        !           200:         * x509 constraints and other flags
        !           201:         */
        !           202:        x509_flag_t flags;
        !           203: 
        !           204:        /**
        !           205:         * Signature scheme
        !           206:         */
        !           207:        signature_params_t *scheme;
        !           208: 
        !           209:        /**
        !           210:         * Signature
        !           211:         */
        !           212:        chunk_t signature;
        !           213: 
        !           214:        /**
        !           215:         * Certificate parsed from blob/file?
        !           216:         */
        !           217:        bool parsed;
        !           218: 
        !           219:        /**
        !           220:         * reference count
        !           221:         */
        !           222:        refcount_t ref;
        !           223: };
        !           224: 
        !           225: /**
        !           226:  * Convert a generalName to a string
        !           227:  */
        !           228: static bool gn_to_string(identification_t *id, char **uri)
        !           229: {
        !           230:        int len;
        !           231: 
        !           232: #ifdef USE_FUZZING
        !           233:        chunk_t proper;
        !           234:        chunk_printable(id->get_encoding(id), &proper, '?');
        !           235:        len = asprintf(uri, "%.*s", (int)proper.len, proper.ptr);
        !           236:        chunk_free(&proper);
        !           237: #else
        !           238:        len = asprintf(uri, "%Y", id);
        !           239: #endif
        !           240:        if (!len)
        !           241:        {
        !           242:                free(*uri);
        !           243:                return FALSE;
        !           244:        }
        !           245:        return len > 0;
        !           246: }
        !           247: 
        !           248: /**
        !           249:  * Destroy a CertificatePolicy
        !           250:  */
        !           251: static void cert_policy_destroy(x509_cert_policy_t *this)
        !           252: {
        !           253:        free(this->oid.ptr);
        !           254:        free(this->cps_uri);
        !           255:        free(this->unotice_text);
        !           256:        free(this);
        !           257: }
        !           258: 
        !           259: /**
        !           260:  * Free policy mapping
        !           261:  */
        !           262: static void policy_mapping_destroy(x509_policy_mapping_t *mapping)
        !           263: {
        !           264:        free(mapping->issuer.ptr);
        !           265:        free(mapping->subject.ptr);
        !           266:        free(mapping);
        !           267: }
        !           268: 
        !           269: /**
        !           270:  * Parse a length constraint from an unwrapped integer
        !           271:  */
        !           272: static u_int parse_constraint(chunk_t object)
        !           273: {
        !           274:        switch (object.len)
        !           275:        {
        !           276:                case 0:
        !           277:                        return 0;
        !           278:                case 1:
        !           279:                        return (object.ptr[0] & 0x80) ? X509_NO_CONSTRAINT : object.ptr[0];
        !           280:                default:
        !           281:                        return X509_NO_CONSTRAINT;
        !           282:        }
        !           283: }
        !           284: 
        !           285: /**
        !           286:  * ASN.1 definition of a basicConstraints extension
        !           287:  */
        !           288: static const asn1Object_t basicConstraintsObjects[] = {
        !           289:        { 0, "basicConstraints",        ASN1_SEQUENCE,  ASN1_NONE                       }, /*  0 */
        !           290:        { 1,   "CA",                            ASN1_BOOLEAN,   ASN1_DEF|ASN1_BODY      }, /*  1 */
        !           291:        { 1,   "pathLenConstraint",     ASN1_INTEGER,   ASN1_OPT|ASN1_BODY      }, /*  2 */
        !           292:        { 1,   "end opt",                       ASN1_EOC,               ASN1_END                        }, /*  3 */
        !           293:        { 0, "exit",                            ASN1_EOC,               ASN1_EXIT                       }
        !           294: };
        !           295: #define BASIC_CONSTRAINTS_CA           1
        !           296: #define BASIC_CONSTRAINTS_PATH_LEN     2
        !           297: 
        !           298: /**
        !           299:  * Extracts the basicConstraints extension
        !           300:  */
        !           301: static bool parse_basicConstraints(chunk_t blob, int level0,
        !           302:                                                                   private_x509_cert_t *this)
        !           303: {
        !           304:        asn1_parser_t *parser;
        !           305:        chunk_t object;
        !           306:        int objectID;
        !           307:        bool isCA = FALSE;
        !           308:        bool success;
        !           309: 
        !           310:        parser = asn1_parser_create(basicConstraintsObjects, blob);
        !           311:        parser->set_top_level(parser, level0);
        !           312: 
        !           313:        while (parser->iterate(parser, &objectID, &object))
        !           314:        {
        !           315:                switch (objectID)
        !           316:                {
        !           317:                        case BASIC_CONSTRAINTS_CA:
        !           318:                                isCA = object.len && *object.ptr;
        !           319:                                DBG2(DBG_ASN, "  %s", isCA ? "TRUE" : "FALSE");
        !           320:                                if (isCA)
        !           321:                                {
        !           322:                                        this->flags |= X509_CA;
        !           323:                                }
        !           324:                                break;
        !           325:                        case BASIC_CONSTRAINTS_PATH_LEN:
        !           326:                                if (isCA)
        !           327:                                {
        !           328:                                        this->pathLenConstraint = parse_constraint(object);
        !           329:                                }
        !           330:                                break;
        !           331:                        default:
        !           332:                                break;
        !           333:                }
        !           334:        }
        !           335:        success = parser->success(parser);
        !           336:        parser->destroy(parser);
        !           337: 
        !           338:        return success;
        !           339: }
        !           340: 
        !           341: /**
        !           342:  * ASN.1 definition of otherName
        !           343:  */
        !           344: static const asn1Object_t otherNameObjects[] = {
        !           345:        {0, "type-id",  ASN1_OID,                       ASN1_BODY       }, /* 0 */
        !           346:        {0, "value",    ASN1_CONTEXT_C_0,       ASN1_BODY       }, /* 1 */
        !           347:        {0, "exit",             ASN1_EOC,                       ASN1_EXIT       }
        !           348: };
        !           349: #define ON_OBJ_ID_TYPE         0
        !           350: #define ON_OBJ_VALUE           1
        !           351: 
        !           352: /**
        !           353:  * Extracts an otherName
        !           354:  */
        !           355: static bool parse_otherName(chunk_t *blob, int level0, id_type_t *type)
        !           356: {
        !           357:        asn1_parser_t *parser;
        !           358:        chunk_t object;
        !           359:        int objectID;
        !           360:        int oid = OID_UNKNOWN;
        !           361:        bool success = FALSE;
        !           362: 
        !           363:        parser = asn1_parser_create(otherNameObjects, *blob);
        !           364:        parser->set_top_level(parser, level0);
        !           365: 
        !           366:        while (parser->iterate(parser, &objectID, &object))
        !           367:        {
        !           368:                switch (objectID)
        !           369:                {
        !           370:                        case ON_OBJ_ID_TYPE:
        !           371:                                oid = asn1_known_oid(object);
        !           372:                                break;
        !           373:                        case ON_OBJ_VALUE:
        !           374:                                switch (oid)
        !           375:                                {
        !           376:                                        case OID_XMPP_ADDR:
        !           377:                                                if (asn1_parse_simple_object(&object, ASN1_UTF8STRING,
        !           378:                                                                        parser->get_level(parser)+1, "xmppAddr"))
        !           379:                                                {       /* we handle xmppAddr as RFC822 addr */
        !           380:                                                        *blob = object;
        !           381:                                                        *type = ID_RFC822_ADDR;
        !           382:                                                }
        !           383:                                                else
        !           384:                                                {
        !           385:                                                        goto end;
        !           386:                                                }
        !           387:                                                break;
        !           388:                                        case OID_USER_PRINCIPAL_NAME:
        !           389:                                                if (asn1_parse_simple_object(&object, ASN1_UTF8STRING,
        !           390:                                                                        parser->get_level(parser)+1, "msUPN"))
        !           391:                                                {       /* we handle UPNs as RFC822 addr */
        !           392:                                                        *blob = object;
        !           393:                                                        *type = ID_RFC822_ADDR;
        !           394:                                                }
        !           395:                                                else
        !           396:                                                {
        !           397:                                                        goto end;
        !           398:                                                }
        !           399:                                                break;
        !           400:                                }
        !           401:                                break;
        !           402:                        default:
        !           403:                                break;
        !           404:                }
        !           405:        }
        !           406:        success = parser->success(parser);
        !           407: 
        !           408: end:
        !           409:        parser->destroy(parser);
        !           410:        return success;
        !           411: }
        !           412: 
        !           413: /**
        !           414:  * ASN.1 definition of generalName
        !           415:  */
        !           416: static const asn1Object_t generalNameObjects[] = {
        !           417:        { 0, "otherName",               ASN1_CONTEXT_C_0,  ASN1_OPT|ASN1_BODY   }, /*  0 */
        !           418:        { 0, "end choice",              ASN1_EOC,          ASN1_END                             }, /*  1 */
        !           419:        { 0, "rfc822Name",              ASN1_CONTEXT_S_1,  ASN1_OPT|ASN1_BODY   }, /*  2 */
        !           420:        { 0, "end choice",              ASN1_EOC,          ASN1_END                             }, /*  3 */
        !           421:        { 0, "dnsName",                 ASN1_CONTEXT_S_2,  ASN1_OPT|ASN1_BODY   }, /*  4 */
        !           422:        { 0, "end choice",              ASN1_EOC,          ASN1_END                             }, /*  5 */
        !           423:        { 0, "x400Address",             ASN1_CONTEXT_S_3,  ASN1_OPT|ASN1_BODY   }, /*  6 */
        !           424:        { 0, "end choice",              ASN1_EOC,          ASN1_END                             }, /*  7 */
        !           425:        { 0, "directoryName",   ASN1_CONTEXT_C_4,  ASN1_OPT|ASN1_BODY   }, /*  8 */
        !           426:        { 0, "end choice",              ASN1_EOC,          ASN1_END                             }, /*  9 */
        !           427:        { 0, "ediPartyName",    ASN1_CONTEXT_C_5,  ASN1_OPT|ASN1_BODY   }, /* 10 */
        !           428:        { 0, "end choice",              ASN1_EOC,          ASN1_END                             }, /* 11 */
        !           429:        { 0, "URI",                             ASN1_CONTEXT_S_6,  ASN1_OPT|ASN1_BODY   }, /* 12 */
        !           430:        { 0, "end choice",              ASN1_EOC,          ASN1_END                             }, /* 13 */
        !           431:        { 0, "ipAddress",               ASN1_CONTEXT_S_7,  ASN1_OPT|ASN1_BODY   }, /* 14 */
        !           432:        { 0, "end choice",              ASN1_EOC,          ASN1_END                             }, /* 15 */
        !           433:        { 0, "registeredID",    ASN1_CONTEXT_S_8,  ASN1_OPT|ASN1_BODY   }, /* 16 */
        !           434:        { 0, "end choice",              ASN1_EOC,          ASN1_END                             }, /* 17 */
        !           435:        { 0, "exit",                    ASN1_EOC,          ASN1_EXIT                    }
        !           436: };
        !           437: #define GN_OBJ_OTHER_NAME               0
        !           438: #define GN_OBJ_RFC822_NAME              2
        !           439: #define GN_OBJ_DNS_NAME                         4
        !           440: #define GN_OBJ_X400_ADDRESS             6
        !           441: #define GN_OBJ_DIRECTORY_NAME   8
        !           442: #define GN_OBJ_EDI_PARTY_NAME  10
        !           443: #define GN_OBJ_URI                             12
        !           444: #define GN_OBJ_IP_ADDRESS              14
        !           445: #define GN_OBJ_REGISTERED_ID   16
        !           446: 
        !           447: /**
        !           448:  * Extracts a generalName
        !           449:  */
        !           450: static identification_t *parse_generalName(chunk_t blob, int level0)
        !           451: {
        !           452:        asn1_parser_t *parser;
        !           453:        chunk_t object;
        !           454:        int objectID ;
        !           455: 
        !           456:        identification_t *gn = NULL;
        !           457: 
        !           458:        parser = asn1_parser_create(generalNameObjects, blob);
        !           459:        parser->set_top_level(parser, level0);
        !           460: 
        !           461:        while (parser->iterate(parser, &objectID, &object))
        !           462:        {
        !           463:                id_type_t id_type = ID_ANY;
        !           464: 
        !           465:                switch (objectID)
        !           466:                {
        !           467:                        case GN_OBJ_RFC822_NAME:
        !           468:                                id_type = ID_RFC822_ADDR;
        !           469:                                break;
        !           470:                        case GN_OBJ_DNS_NAME:
        !           471:                                id_type = ID_FQDN;
        !           472:                                break;
        !           473:                        case GN_OBJ_URI:
        !           474:                                id_type = ID_DER_ASN1_GN_URI;
        !           475:                                break;
        !           476:                        case GN_OBJ_DIRECTORY_NAME:
        !           477:                                id_type = ID_DER_ASN1_DN;
        !           478:                                break;
        !           479:                        case GN_OBJ_IP_ADDRESS:
        !           480:                                switch (object.len)
        !           481:                                {
        !           482:                                        case 4:
        !           483:                                                id_type = ID_IPV4_ADDR;
        !           484:                                                break;
        !           485:                                        case 16:
        !           486:                                                id_type = ID_IPV6_ADDR;
        !           487:                                                break;
        !           488:                                        default:
        !           489:                                                break;
        !           490:                                }
        !           491:                                break;
        !           492:                        case GN_OBJ_OTHER_NAME:
        !           493:                                if (!parse_otherName(&object, parser->get_level(parser)+1,
        !           494:                                                                         &id_type))
        !           495:                                {
        !           496:                                        goto end;
        !           497:                                }
        !           498:                                break;
        !           499:                        case GN_OBJ_X400_ADDRESS:
        !           500:                        case GN_OBJ_EDI_PARTY_NAME:
        !           501:                        case GN_OBJ_REGISTERED_ID:
        !           502:                        default:
        !           503:                                break;
        !           504:                }
        !           505:                if (id_type != ID_ANY)
        !           506:                {
        !           507:                        gn = identification_create_from_encoding(id_type, object);
        !           508:                        DBG2(DBG_ASN, "  '%Y'", gn);
        !           509:                        goto end;
        !           510:                }
        !           511:        }
        !           512: 
        !           513: end:
        !           514:        parser->destroy(parser);
        !           515:        return gn;
        !           516: }
        !           517: 
        !           518: /**
        !           519:  * ASN.1 definition of generalNames
        !           520:  */
        !           521: static const asn1Object_t generalNamesObjects[] = {
        !           522:        { 0, "generalNames",    ASN1_SEQUENCE,  ASN1_LOOP }, /* 0 */
        !           523:        { 1,   "generalName",   ASN1_EOC,               ASN1_RAW  }, /* 1 */
        !           524:        { 0, "end loop",                ASN1_EOC,               ASN1_END  }, /* 2 */
        !           525:        { 0, "exit",                    ASN1_EOC,               ASN1_EXIT }
        !           526: };
        !           527: #define GENERAL_NAMES_GN       1
        !           528: 
        !           529: /**
        !           530:  * Extracts one or several GNs and puts them into a chained list
        !           531:  */
        !           532: bool x509_parse_generalNames(chunk_t blob, int level0, bool implicit,
        !           533:                                                         linked_list_t *list)
        !           534: {
        !           535:        asn1_parser_t *parser;
        !           536:        chunk_t object;
        !           537:        identification_t *gn;
        !           538:        int objectID;
        !           539:        bool success = FALSE;
        !           540: 
        !           541:        parser = asn1_parser_create(generalNamesObjects, blob);
        !           542:        parser->set_top_level(parser, level0);
        !           543:        parser->set_flags(parser, implicit, FALSE);
        !           544: 
        !           545:        while (parser->iterate(parser, &objectID, &object))
        !           546:        {
        !           547:                if (objectID == GENERAL_NAMES_GN)
        !           548:                {
        !           549:                        gn = parse_generalName(object, parser->get_level(parser)+1);
        !           550:                        if (!gn)
        !           551:                        {
        !           552:                                goto end;
        !           553:                        }
        !           554:                        list->insert_last(list, (void *)gn);
        !           555:                }
        !           556:        }
        !           557:        success = parser->success(parser);
        !           558: 
        !           559: end:
        !           560:        parser->destroy(parser);
        !           561: 
        !           562:        return success;
        !           563: }
        !           564: 
        !           565: /**
        !           566:  * ASN.1 definition of a authorityKeyIdentifier extension
        !           567:  */
        !           568: static const asn1Object_t authKeyIdentifierObjects[] = {
        !           569:        { 0, "authorityKeyIdentifier",          ASN1_SEQUENCE,          ASN1_NONE                       }, /* 0 */
        !           570:        { 1,   "keyIdentifier",                         ASN1_CONTEXT_S_0,       ASN1_OPT|ASN1_BODY      }, /* 1 */
        !           571:        { 1,   "end opt",                                       ASN1_EOC,                       ASN1_END                        }, /* 2 */
        !           572:        { 1,   "authorityCertIssuer",           ASN1_CONTEXT_C_1,       ASN1_OPT|ASN1_OBJ       }, /* 3 */
        !           573:        { 1,   "end opt",                                       ASN1_EOC,                       ASN1_END                        }, /* 4 */
        !           574:        { 1,   "authorityCertSerialNumber",     ASN1_CONTEXT_S_2,       ASN1_OPT|ASN1_BODY      }, /* 5 */
        !           575:        { 1,   "end opt",                                       ASN1_EOC,                       ASN1_END                        }, /* 6 */
        !           576:        { 0, "exit",                                            ASN1_EOC,                       ASN1_EXIT                       }
        !           577: };
        !           578: #define AUTH_KEY_ID_KEY_ID                     1
        !           579: #define AUTH_KEY_ID_CERT_ISSUER                3
        !           580: #define AUTH_KEY_ID_CERT_SERIAL                5
        !           581: 
        !           582: /**
        !           583:  * Extracts an authoritykeyIdentifier
        !           584:  */
        !           585: chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob, int level0,
        !           586:                                                                                                chunk_t *authKeySerialNumber)
        !           587: {
        !           588:        asn1_parser_t *parser;
        !           589:        chunk_t object;
        !           590:        int objectID;
        !           591:        chunk_t authKeyIdentifier = chunk_empty;
        !           592: 
        !           593:        *authKeySerialNumber = chunk_empty;
        !           594: 
        !           595:        parser = asn1_parser_create(authKeyIdentifierObjects, blob);
        !           596:        parser->set_top_level(parser, level0);
        !           597: 
        !           598:        while (parser->iterate(parser, &objectID, &object))
        !           599:        {
        !           600:                switch (objectID)
        !           601:                {
        !           602:                        case AUTH_KEY_ID_KEY_ID:
        !           603:                                authKeyIdentifier = chunk_clone(object);
        !           604:                                break;
        !           605:                        case AUTH_KEY_ID_CERT_ISSUER:
        !           606:                                /* TODO: x509_parse_generalNames(object, level+1, TRUE); */
        !           607:                                break;
        !           608:                        case AUTH_KEY_ID_CERT_SERIAL:
        !           609:                                *authKeySerialNumber = object;
        !           610:                                break;
        !           611:                        default:
        !           612:                                break;
        !           613:                }
        !           614:        }
        !           615:        parser->destroy(parser);
        !           616: 
        !           617:        return authKeyIdentifier;
        !           618: }
        !           619: 
        !           620: /**
        !           621:  * ASN.1 definition of a authorityInfoAccess extension
        !           622:  */
        !           623: static const asn1Object_t authInfoAccessObjects[] = {
        !           624:        { 0, "authorityInfoAccess",     ASN1_SEQUENCE,  ASN1_LOOP }, /* 0 */
        !           625:        { 1,   "accessDescription",     ASN1_SEQUENCE,  ASN1_NONE }, /* 1 */
        !           626:        { 2,     "accessMethod",        ASN1_OID,               ASN1_BODY }, /* 2 */
        !           627:        { 2,     "accessLocation",      ASN1_EOC,               ASN1_RAW  }, /* 3 */
        !           628:        { 0, "end loop",                        ASN1_EOC,               ASN1_END  }, /* 4 */
        !           629:        { 0, "exit",                            ASN1_EOC,               ASN1_EXIT }
        !           630: };
        !           631: #define AUTH_INFO_ACCESS_METHOD                2
        !           632: #define AUTH_INFO_ACCESS_LOCATION      3
        !           633: 
        !           634: /**
        !           635:  * Extracts an authorityInfoAcess location
        !           636:  */
        !           637: static bool parse_authorityInfoAccess(chunk_t blob, int level0,
        !           638:                                                                          private_x509_cert_t *this)
        !           639: {
        !           640:        asn1_parser_t *parser;
        !           641:        chunk_t object;
        !           642:        int objectID;
        !           643:        int accessMethod = OID_UNKNOWN;
        !           644:        bool success = FALSE;
        !           645: 
        !           646:        parser = asn1_parser_create(authInfoAccessObjects, blob);
        !           647:        parser->set_top_level(parser, level0);
        !           648: 
        !           649:        while (parser->iterate(parser, &objectID, &object))
        !           650:        {
        !           651:                switch (objectID)
        !           652:                {
        !           653:                        case AUTH_INFO_ACCESS_METHOD:
        !           654:                                accessMethod = asn1_known_oid(object);
        !           655:                                break;
        !           656:                        case AUTH_INFO_ACCESS_LOCATION:
        !           657:                        {
        !           658:                                switch (accessMethod)
        !           659:                                {
        !           660:                                        case OID_OCSP:
        !           661:                                        case OID_CA_ISSUERS:
        !           662:                                                {
        !           663:                                                        identification_t *id;
        !           664:                                                        char *uri;
        !           665: 
        !           666:                                                        id = parse_generalName(object,
        !           667:                                                                                        parser->get_level(parser)+1);
        !           668:                                                        if (id == NULL)
        !           669:                                                        {
        !           670:                                                                /* parsing went wrong - abort */
        !           671:                                                                goto end;
        !           672:                                                        }
        !           673:                                                        DBG2(DBG_ASN, "  '%Y'", id);
        !           674:                                                        if (accessMethod == OID_OCSP &&
        !           675:                                                                gn_to_string(id, &uri))
        !           676:                                                        {
        !           677:                                                                this->ocsp_uris->insert_last(this->ocsp_uris, uri);
        !           678:                                                        }
        !           679:                                                        id->destroy(id);
        !           680:                                                }
        !           681:                                                break;
        !           682:                                        default:
        !           683:                                                /* unknown accessMethod, ignoring */
        !           684:                                                break;
        !           685:                                }
        !           686:                                break;
        !           687:                        }
        !           688:                        default:
        !           689:                                break;
        !           690:                }
        !           691:        }
        !           692:        success = parser->success(parser);
        !           693: 
        !           694: end:
        !           695:        parser->destroy(parser);
        !           696: 
        !           697:        return success;
        !           698: }
        !           699: 
        !           700: /**
        !           701:  * Extract KeyUsage flags
        !           702:  */
        !           703: static void parse_keyUsage(chunk_t blob, private_x509_cert_t *this)
        !           704: {
        !           705:        enum {
        !           706:                KU_DIGITAL_SIGNATURE =  0,
        !           707:                KU_NON_REPUDIATION =    1,
        !           708:                KU_KEY_ENCIPHERMENT =   2,
        !           709:                KU_DATA_ENCIPHERMENT =  3,
        !           710:                KU_KEY_AGREEMENT =              4,
        !           711:                KU_KEY_CERT_SIGN =              5,
        !           712:                KU_CRL_SIGN =                   6,
        !           713:                KU_ENCIPHER_ONLY =              7,
        !           714:                KU_DECIPHER_ONLY =              8,
        !           715:        };
        !           716: 
        !           717:        /* to be compliant with RFC 4945 specific KUs have to be included */
        !           718:        this->flags &= ~X509_IKE_COMPLIANT;
        !           719: 
        !           720:        if (asn1_unwrap(&blob, &blob) == ASN1_BIT_STRING && blob.len)
        !           721:        {
        !           722:                int bit, byte, unused = blob.ptr[0];
        !           723: 
        !           724:                blob = chunk_skip(blob, 1);
        !           725:                for (byte = 0; byte < blob.len; byte++)
        !           726:                {
        !           727:                        for (bit = 0; bit < 8; bit++)
        !           728:                        {
        !           729:                                if (byte == blob.len - 1 && bit > (7 - unused))
        !           730:                                {
        !           731:                                        break;
        !           732:                                }
        !           733:                                if (blob.ptr[byte] & 1 << (7 - bit))
        !           734:                                {
        !           735:                                        switch (byte * 8 + bit)
        !           736:                                        {
        !           737:                                                case KU_CRL_SIGN:
        !           738:                                                        this->flags |= X509_CRL_SIGN;
        !           739:                                                        break;
        !           740:                                                case KU_DIGITAL_SIGNATURE:
        !           741:                                                case KU_NON_REPUDIATION:
        !           742:                                                        this->flags |= X509_IKE_COMPLIANT;
        !           743:                                                        break;
        !           744:                                                case KU_KEY_CERT_SIGN:
        !           745:                                                        /* we use the caBasicConstraint, MUST be set */
        !           746:                                                case KU_KEY_ENCIPHERMENT:
        !           747:                                                case KU_DATA_ENCIPHERMENT:
        !           748:                                                case KU_KEY_AGREEMENT:
        !           749:                                                case KU_ENCIPHER_ONLY:
        !           750:                                                case KU_DECIPHER_ONLY:
        !           751:                                                        break;
        !           752:                                        }
        !           753:                                }
        !           754:                        }
        !           755:                }
        !           756:        }
        !           757: }
        !           758: 
        !           759: /**
        !           760:  * ASN.1 definition of a extendedKeyUsage extension
        !           761:  */
        !           762: static const asn1Object_t extendedKeyUsageObjects[] = {
        !           763:        { 0, "extendedKeyUsage",        ASN1_SEQUENCE,  ASN1_LOOP }, /* 0 */
        !           764:        { 1,   "keyPurposeID",          ASN1_OID,               ASN1_BODY }, /* 1 */
        !           765:        { 0, "end loop",                        ASN1_EOC,               ASN1_END  }, /* 2 */
        !           766:        { 0, "exit",                            ASN1_EOC,               ASN1_EXIT }
        !           767: };
        !           768: #define EXT_KEY_USAGE_PURPOSE_ID       1
        !           769: 
        !           770: /**
        !           771:  * Extracts extendedKeyUsage OIDs
        !           772:  */
        !           773: static bool parse_extendedKeyUsage(chunk_t blob, int level0,
        !           774:                                                                   private_x509_cert_t *this)
        !           775: {
        !           776:        asn1_parser_t *parser;
        !           777:        chunk_t object;
        !           778:        int objectID;
        !           779:        bool success;
        !           780: 
        !           781:        parser = asn1_parser_create(extendedKeyUsageObjects, blob);
        !           782:        parser->set_top_level(parser, level0);
        !           783: 
        !           784:        while (parser->iterate(parser, &objectID, &object))
        !           785:        {
        !           786:                if (objectID == EXT_KEY_USAGE_PURPOSE_ID)
        !           787:                {
        !           788:                        switch (asn1_known_oid(object))
        !           789:                        {
        !           790:                                case OID_SERVER_AUTH:
        !           791:                                        this->flags |= X509_SERVER_AUTH;
        !           792:                                        break;
        !           793:                                case OID_CLIENT_AUTH:
        !           794:                                        this->flags |= X509_CLIENT_AUTH;
        !           795:                                        break;
        !           796:                                case OID_IKE_INTERMEDIATE:
        !           797:                                        this->flags |= X509_IKE_INTERMEDIATE;
        !           798:                                        break;
        !           799:                                case OID_OCSP_SIGNING:
        !           800:                                        this->flags |= X509_OCSP_SIGNER;
        !           801:                                        break;
        !           802:                                case OID_MS_SMARTCARD_LOGON:
        !           803:                                        this->flags |= X509_MS_SMARTCARD_LOGON;
        !           804:                                        break;
        !           805:                                default:
        !           806:                                        break;
        !           807:                        }
        !           808:                }
        !           809:        }
        !           810:        success = parser->success(parser);
        !           811:        parser->destroy(parser);
        !           812: 
        !           813:        return success;
        !           814: }
        !           815: 
        !           816: /**
        !           817:  * ASN.1 definition of crlDistributionPoints
        !           818:  */
        !           819: static const asn1Object_t crlDistributionPointsObjects[] = {
        !           820:        { 0, "crlDistributionPoints",   ASN1_SEQUENCE,    ASN1_LOOP            }, /*  0 */
        !           821:        { 1,   "DistributionPoint",     ASN1_SEQUENCE,    ASN1_NONE            }, /*  1 */
        !           822:        { 2,     "distributionPoint",   ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_CHOICE }, /*  2 */
        !           823:        { 3,       "fullName",          ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ    }, /*  3 */
        !           824:        { 3,       "end choice",        ASN1_EOC,         ASN1_END|ASN1_CH     }, /*  4 */
        !           825:        { 3,       "nameRelToCRLIssuer",ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY   }, /*  5 */
        !           826:        { 3,       "end choice",        ASN1_EOC,         ASN1_END|ASN1_CH     }, /*  6 */
        !           827:        { 2,     "end opt/choices",     ASN1_EOC,         ASN1_END|ASN1_CHOICE }, /*  7 */
        !           828:        { 2,     "reasons",             ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY   }, /*  8 */
        !           829:        { 2,     "end opt",             ASN1_EOC,         ASN1_END             }, /*  9 */
        !           830:        { 2,     "crlIssuer",           ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_OBJ    }, /* 10 */
        !           831:        { 2,     "end opt",             ASN1_EOC,         ASN1_END             }, /* 11 */
        !           832:        { 0, "end loop",                ASN1_EOC,         ASN1_END             }, /* 12 */
        !           833:        { 0, "exit",                    ASN1_EOC,         ASN1_EXIT            }
        !           834: };
        !           835: #define CRL_DIST_POINTS                                 1
        !           836: #define CRL_DIST_POINTS_FULLNAME        3
        !           837: #define CRL_DIST_POINTS_ISSUER         10
        !           838: 
        !           839: /**
        !           840:  * Add entry to the list of each pairing of URI and Issuer
        !           841:  */
        !           842: static void add_cdps(linked_list_t *list, linked_list_t *uris,
        !           843:                                         linked_list_t *issuers)
        !           844: {
        !           845:        identification_t *issuer, *id;
        !           846:        enumerator_t *enumerator;
        !           847:        x509_cdp_t *cdp;
        !           848:        char *uri;
        !           849: 
        !           850:        while (uris->remove_last(uris, (void**)&id) == SUCCESS)
        !           851:        {
        !           852:                if (gn_to_string(id, &uri))
        !           853:                {
        !           854:                        if (issuers->get_count(issuers))
        !           855:                        {
        !           856:                                enumerator = issuers->create_enumerator(issuers);
        !           857:                                while (enumerator->enumerate(enumerator, &issuer))
        !           858:                                {
        !           859:                                        INIT(cdp,
        !           860:                                                .uri = strdup(uri),
        !           861:                                                .issuer = issuer->clone(issuer),
        !           862:                                        );
        !           863:                                        list->insert_last(list, cdp);
        !           864:                                }
        !           865:                                enumerator->destroy(enumerator);
        !           866:                                free(uri);
        !           867:                        }
        !           868:                        else
        !           869:                        {
        !           870:                                INIT(cdp,
        !           871:                                        .uri = uri,
        !           872:                                );
        !           873:                                list->insert_last(list, cdp);
        !           874:                        }
        !           875:                }
        !           876:                id->destroy(id);
        !           877:        }
        !           878:        while (issuers->remove_last(issuers, (void**)&id) == SUCCESS)
        !           879:        {
        !           880:                id->destroy(id);
        !           881:        }
        !           882: }
        !           883: 
        !           884: /**
        !           885:  * Extracts one or several crlDistributionPoints into a list
        !           886:  */
        !           887: bool x509_parse_crlDistributionPoints(chunk_t blob, int level0,
        !           888:                                                                          linked_list_t *list)
        !           889: {
        !           890:        linked_list_t *uris, *issuers;
        !           891:        asn1_parser_t *parser;
        !           892:        chunk_t object;
        !           893:        int objectID;
        !           894:        bool success = FALSE;
        !           895: 
        !           896:        uris = linked_list_create();
        !           897:        issuers = linked_list_create();
        !           898:        parser = asn1_parser_create(crlDistributionPointsObjects, blob);
        !           899:        parser->set_top_level(parser, level0);
        !           900: 
        !           901:        while (parser->iterate(parser, &objectID, &object))
        !           902:        {
        !           903:                switch (objectID)
        !           904:                {
        !           905:                        case CRL_DIST_POINTS:
        !           906:                                add_cdps(list, uris, issuers);
        !           907:                                break;
        !           908:                        case CRL_DIST_POINTS_FULLNAME:
        !           909:                                if (!x509_parse_generalNames(object,
        !           910:                                                                parser->get_level(parser) + 1, TRUE, uris))
        !           911:                                {
        !           912:                                        goto end;
        !           913:                                }
        !           914:                                break;
        !           915:                        case CRL_DIST_POINTS_ISSUER:
        !           916:                                if (!x509_parse_generalNames(object,
        !           917:                                                                parser->get_level(parser) + 1, TRUE, issuers))
        !           918:                                {
        !           919:                                        goto end;
        !           920:                                }
        !           921:                                break;
        !           922:                        default:
        !           923:                                break;
        !           924:                }
        !           925:        }
        !           926:        success = parser->success(parser);
        !           927:        add_cdps(list, uris, issuers);
        !           928: 
        !           929: end:
        !           930:        parser->destroy(parser);
        !           931:        uris->destroy_offset(uris, offsetof(identification_t, destroy));
        !           932:        issuers->destroy_offset(issuers, offsetof(identification_t, destroy));
        !           933: 
        !           934:        return success;
        !           935: }
        !           936: 
        !           937: /**
        !           938:  * ASN.1 definition of nameConstraints
        !           939:  */
        !           940: static const asn1Object_t nameConstraintsObjects[] = {
        !           941:        { 0, "nameConstraints",                 ASN1_SEQUENCE,          ASN1_NONE                       }, /*  0 */
        !           942:        { 1,   "permittedSubtrees",             ASN1_CONTEXT_C_0,       ASN1_OPT|ASN1_LOOP      }, /*  1 */
        !           943:        { 2,     "generalSubtree",              ASN1_SEQUENCE,          ASN1_BODY                       }, /*  2 */
        !           944:        { 1,   "end loop",                              ASN1_EOC,                       ASN1_END                        }, /*  3 */
        !           945:        { 1,   "excludedSubtrees",              ASN1_CONTEXT_C_1,       ASN1_OPT|ASN1_LOOP      }, /*  4 */
        !           946:        { 2,     "generalSubtree",              ASN1_SEQUENCE,          ASN1_BODY                       }, /*  5 */
        !           947:        { 1,   "end loop",                              ASN1_EOC,                       ASN1_END                        }, /*  6 */
        !           948:        { 0, "exit",                                    ASN1_EOC,                       ASN1_EXIT                       }
        !           949: };
        !           950: #define NAME_CONSTRAINT_PERMITTED 2
        !           951: #define NAME_CONSTRAINT_EXCLUDED  5
        !           952: 
        !           953: /**
        !           954:  * Parse permitted/excluded nameConstraints
        !           955:  */
        !           956: static bool parse_nameConstraints(chunk_t blob, int level0,
        !           957:                                                                  private_x509_cert_t *this)
        !           958: {
        !           959:        asn1_parser_t *parser;
        !           960:        identification_t *id;
        !           961:        chunk_t object;
        !           962:        int objectID;
        !           963:        bool success = FALSE;
        !           964: 
        !           965:        parser = asn1_parser_create(nameConstraintsObjects, blob);
        !           966:        parser->set_top_level(parser, level0);
        !           967: 
        !           968:        while (parser->iterate(parser, &objectID, &object))
        !           969:        {
        !           970:                switch (objectID)
        !           971:                {
        !           972:                        case NAME_CONSTRAINT_PERMITTED:
        !           973:                                id = parse_generalName(object, parser->get_level(parser) + 1);
        !           974:                                if (!id)
        !           975:                                {
        !           976:                                        goto end;
        !           977:                                }
        !           978:                                this->permitted_names->insert_last(this->permitted_names, id);
        !           979:                                break;
        !           980:                        case NAME_CONSTRAINT_EXCLUDED:
        !           981:                                id = parse_generalName(object, parser->get_level(parser) + 1);
        !           982:                                if (!id)
        !           983:                                {
        !           984:                                        goto end;
        !           985:                                }
        !           986:                                this->excluded_names->insert_last(this->excluded_names, id);
        !           987:                                break;
        !           988:                        default:
        !           989:                                break;
        !           990:                }
        !           991:        }
        !           992:        success = parser->success(parser);
        !           993: 
        !           994: end:
        !           995:        parser->destroy(parser);
        !           996: 
        !           997:        return success;
        !           998: }
        !           999: 
        !          1000: /**
        !          1001:  * ASN.1 definition of a certificatePolicies extension
        !          1002:  */
        !          1003: static const asn1Object_t certificatePoliciesObject[] = {
        !          1004:        { 0, "certificatePolicies",      ASN1_SEQUENCE,  ASN1_LOOP            }, /*  0 */
        !          1005:        { 1,   "policyInformation",      ASN1_SEQUENCE,  ASN1_NONE            }, /*  1 */
        !          1006:        { 2,     "policyId",             ASN1_OID,       ASN1_BODY            }, /*  2 */
        !          1007:        { 2,     "qualifiers",           ASN1_SEQUENCE,  ASN1_OPT|ASN1_LOOP   }, /*  3 */
        !          1008:        { 3,       "qualifierInfo",      ASN1_SEQUENCE,  ASN1_NONE            }, /*  4 */
        !          1009:        { 4,         "qualifierId",      ASN1_OID,       ASN1_BODY            }, /*  5 */
        !          1010:        { 4,         "qualifier",        ASN1_EOC,       ASN1_CHOICE          }, /*  6 */
        !          1011:        { 5,           "cPSuri",         ASN1_IA5STRING, ASN1_OPT|ASN1_BODY   }, /*  7 */
        !          1012:        { 5,           "end choice",     ASN1_EOC,       ASN1_END|ASN1_CH     }, /*  8 */
        !          1013:        { 5,           "userNotice",     ASN1_SEQUENCE,  ASN1_OPT|ASN1_BODY   }, /*  9 */
        !          1014:        { 6,             "explicitText", ASN1_EOC,       ASN1_RAW             }, /* 10 */
        !          1015:        { 5,           "end choice",     ASN1_EOC,       ASN1_END|ASN1_CH     }, /* 11 */
        !          1016:        { 4,         "end choices",      ASN1_EOC,       ASN1_END|ASN1_CHOICE }, /* 12 */
        !          1017:        { 2,     "end opt/loop",         ASN1_EOC,       ASN1_END             }, /* 13 */
        !          1018:        { 0, "end loop",                 ASN1_EOC,       ASN1_END             }, /* 14 */
        !          1019:        { 0, "exit",                     ASN1_EOC,       ASN1_EXIT            }
        !          1020: };
        !          1021: #define CERT_POLICY_ID              2
        !          1022: #define CERT_POLICY_QUALIFIER_ID    5
        !          1023: #define CERT_POLICY_CPS_URI         7
        !          1024: #define CERT_POLICY_EXPLICIT_TEXT  10
        !          1025: 
        !          1026: /**
        !          1027:  * Parse certificatePolicies
        !          1028:  */
        !          1029: static bool parse_certificatePolicies(chunk_t blob, int level0,
        !          1030:                                                                          private_x509_cert_t *this)
        !          1031: {
        !          1032:        x509_cert_policy_t *policy = NULL;
        !          1033:        asn1_parser_t *parser;
        !          1034:        chunk_t object;
        !          1035:        int objectID, qualifier = OID_UNKNOWN;
        !          1036:        bool success;
        !          1037: 
        !          1038:        parser = asn1_parser_create(certificatePoliciesObject, blob);
        !          1039:        parser->set_top_level(parser, level0);
        !          1040: 
        !          1041:        while (parser->iterate(parser, &objectID, &object))
        !          1042:        {
        !          1043:                switch (objectID)
        !          1044:                {
        !          1045:                        case CERT_POLICY_ID:
        !          1046:                                INIT(policy,
        !          1047:                                        .oid = chunk_clone(object),
        !          1048:                                );
        !          1049:                                this->cert_policies->insert_last(this->cert_policies, policy);
        !          1050:                                break;
        !          1051:                        case CERT_POLICY_QUALIFIER_ID:
        !          1052:                                qualifier = asn1_known_oid(object);
        !          1053:                                break;
        !          1054:                        case CERT_POLICY_CPS_URI:
        !          1055:                                if (policy && !policy->cps_uri && object.len &&
        !          1056:                                        qualifier == OID_POLICY_QUALIFIER_CPS &&
        !          1057:                                        chunk_printable(object, NULL, 0))
        !          1058:                                {
        !          1059:                                        policy->cps_uri = strndup(object.ptr, object.len);
        !          1060:                                }
        !          1061:                                break;
        !          1062:                        case CERT_POLICY_EXPLICIT_TEXT:
        !          1063:                                /* TODO */
        !          1064:                                break;
        !          1065:                        default:
        !          1066:                                break;
        !          1067:                }
        !          1068:        }
        !          1069:        success = parser->success(parser);
        !          1070:        parser->destroy(parser);
        !          1071: 
        !          1072:        return success;
        !          1073: }
        !          1074: 
        !          1075: /**
        !          1076:  * ASN.1 definition of a policyMappings extension
        !          1077:  */
        !          1078: static const asn1Object_t policyMappingsObjects[] = {
        !          1079:        { 0, "policyMappings",                  ASN1_SEQUENCE,  ASN1_LOOP                       }, /*  0 */
        !          1080:        { 1,   "policyMapping",                 ASN1_SEQUENCE,  ASN1_NONE                       }, /*  1 */
        !          1081:        { 2,     "issuerPolicy",                ASN1_OID,               ASN1_BODY                       }, /*  2 */
        !          1082:        { 2,     "subjectPolicy",               ASN1_OID,               ASN1_BODY                       }, /*  3 */
        !          1083:        { 0, "end loop",                                ASN1_EOC,               ASN1_END                        }, /*  4 */
        !          1084:        { 0, "exit",                                    ASN1_EOC,               ASN1_EXIT                       }
        !          1085: };
        !          1086: #define POLICY_MAPPING                 1
        !          1087: #define POLICY_MAPPING_ISSUER  2
        !          1088: #define POLICY_MAPPING_SUBJECT 3
        !          1089: 
        !          1090: /**
        !          1091:  * Parse policyMappings
        !          1092:  */
        !          1093: static bool parse_policyMappings(chunk_t blob, int level0,
        !          1094:                                                                 private_x509_cert_t *this)
        !          1095: {
        !          1096:        x509_policy_mapping_t *map = NULL;
        !          1097:        asn1_parser_t *parser;
        !          1098:        chunk_t object;
        !          1099:        int objectID;
        !          1100:        bool success;
        !          1101: 
        !          1102:        parser = asn1_parser_create(policyMappingsObjects, blob);
        !          1103:        parser->set_top_level(parser, level0);
        !          1104: 
        !          1105:        while (parser->iterate(parser, &objectID, &object))
        !          1106:        {
        !          1107:                switch (objectID)
        !          1108:                {
        !          1109:                        case POLICY_MAPPING:
        !          1110:                                INIT(map);
        !          1111:                                this->policy_mappings->insert_last(this->policy_mappings, map);
        !          1112:                                break;
        !          1113:                        case POLICY_MAPPING_ISSUER:
        !          1114:                                if (map && !map->issuer.len)
        !          1115:                                {
        !          1116:                                        map->issuer = chunk_clone(object);
        !          1117:                                }
        !          1118:                                break;
        !          1119:                        case POLICY_MAPPING_SUBJECT:
        !          1120:                                if (map && !map->subject.len)
        !          1121:                                {
        !          1122:                                        map->subject = chunk_clone(object);
        !          1123:                                }
        !          1124:                                break;
        !          1125:                        default:
        !          1126:                                break;
        !          1127:                }
        !          1128:        }
        !          1129:        success = parser->success(parser);
        !          1130:        parser->destroy(parser);
        !          1131: 
        !          1132:        return success;
        !          1133: }
        !          1134: 
        !          1135: /**
        !          1136:  * ASN.1 definition of a policyConstraints extension
        !          1137:  */
        !          1138: static const asn1Object_t policyConstraintsObjects[] = {
        !          1139:        { 0, "policyConstraints",               ASN1_SEQUENCE,          ASN1_NONE                       }, /*  0 */
        !          1140:        { 1,   "requireExplicitPolicy", ASN1_CONTEXT_C_0,       ASN1_OPT|ASN1_NONE      }, /*  1 */
        !          1141:        { 2,     "SkipCerts",                   ASN1_INTEGER,           ASN1_BODY                       }, /*  2 */
        !          1142:        { 1,   "end opt",                               ASN1_EOC,                       ASN1_END                        }, /*  3 */
        !          1143:        { 1,   "inhibitPolicyMapping",  ASN1_CONTEXT_C_1,       ASN1_OPT|ASN1_NONE      }, /*  4 */
        !          1144:        { 2,     "SkipCerts",                   ASN1_INTEGER,           ASN1_BODY                       }, /*  5 */
        !          1145:        { 1,   "end opt",                               ASN1_EOC,                       ASN1_END                        }, /*  6 */
        !          1146:        { 0, "exit",                                    ASN1_EOC,                       ASN1_EXIT                       }
        !          1147: };
        !          1148: #define POLICY_CONSTRAINT_EXPLICIT 2
        !          1149: #define POLICY_CONSTRAINT_INHIBIT  5
        !          1150: 
        !          1151: /**
        !          1152:  * Parse policyConstraints
        !          1153:  */
        !          1154: static bool parse_policyConstraints(chunk_t blob, int level0,
        !          1155:                                                                        private_x509_cert_t *this)
        !          1156: {
        !          1157:        asn1_parser_t *parser;
        !          1158:        chunk_t object;
        !          1159:        int objectID;
        !          1160:        bool success;
        !          1161: 
        !          1162:        parser = asn1_parser_create(policyConstraintsObjects, blob);
        !          1163:        parser->set_top_level(parser, level0);
        !          1164: 
        !          1165:        while (parser->iterate(parser, &objectID, &object))
        !          1166:        {
        !          1167:                switch (objectID)
        !          1168:                {
        !          1169:                        case POLICY_CONSTRAINT_EXPLICIT:
        !          1170:                                this->require_explicit = parse_constraint(object);
        !          1171:                                break;
        !          1172:                        case POLICY_CONSTRAINT_INHIBIT:
        !          1173:                                this->inhibit_mapping = parse_constraint(object);
        !          1174:                                break;
        !          1175:                        default:
        !          1176:                                break;
        !          1177:                }
        !          1178:        }
        !          1179:        success = parser->success(parser);
        !          1180:        parser->destroy(parser);
        !          1181: 
        !          1182:        return success;
        !          1183: }
        !          1184: 
        !          1185: /**
        !          1186:  * ASN.1 definition of ipAddrBlocks according to RFC 3779
        !          1187:  */
        !          1188: static const asn1Object_t ipAddrBlocksObjects[] = {
        !          1189:        { 0, "ipAddrBlocks",            ASN1_SEQUENCE,     ASN1_LOOP            }, /*  0 */
        !          1190:        { 1,   "ipAddressFamily",       ASN1_SEQUENCE,     ASN1_NONE            }, /*  1 */
        !          1191:        { 2,     "addressFamily",       ASN1_OCTET_STRING, ASN1_BODY            }, /*  2 */
        !          1192:        { 2,     "ipAddressChoice",     ASN1_EOC,          ASN1_CHOICE          }, /*  3 */
        !          1193:        { 3,       "inherit",           ASN1_NULL,         ASN1_OPT             }, /*  4 */
        !          1194:        { 3,       "end choice",        ASN1_EOC,          ASN1_END|ASN1_CH     }, /*  5 */
        !          1195:        { 3,       "addressesOrRanges", ASN1_SEQUENCE,     ASN1_OPT|ASN1_LOOP   }, /*  6 */
        !          1196:        { 4,         "addressOrRange",  ASN1_EOC,          ASN1_CHOICE          }, /*  7 */
        !          1197:        { 5,           "addressPrefix", ASN1_BIT_STRING,   ASN1_OPT|ASN1_BODY   }, /*  8 */
        !          1198:        { 5,           "end choice",    ASN1_EOC,          ASN1_END|ASN1_CH     }, /*  9 */
        !          1199:        { 5,           "addressRange",  ASN1_SEQUENCE,     ASN1_OPT             }, /* 10 */
        !          1200:        { 6,             "min",         ASN1_BIT_STRING,   ASN1_BODY            }, /* 11 */
        !          1201:        { 6,             "max",         ASN1_BIT_STRING,   ASN1_BODY            }, /* 12 */
        !          1202:        { 5,           "end choice",    ASN1_EOC,          ASN1_END|ASN1_CH     }, /* 13 */
        !          1203:        { 4,         "end choices",     ASN1_EOC,          ASN1_END|ASN1_CHOICE }, /* 14 */
        !          1204:        { 3,       "end loop/choice",   ASN1_EOC,          ASN1_END|ASN1_CH     }, /* 15 */
        !          1205:        { 2,     "end choices",         ASN1_EOC,          ASN1_END|ASN1_CHOICE }, /* 16 */
        !          1206:        { 0, "end loop",                ASN1_EOC,          ASN1_END             }, /* 17 */
        !          1207:        { 0, "exit",                    ASN1_EOC,          ASN1_EXIT            }
        !          1208: };
        !          1209: #define IP_ADDR_BLOCKS_FAMILY       2
        !          1210: #define IP_ADDR_BLOCKS_INHERIT      4
        !          1211: #define IP_ADDR_BLOCKS_PREFIX       8
        !          1212: #define IP_ADDR_BLOCKS_MIN         11
        !          1213: #define IP_ADDR_BLOCKS_MAX         12
        !          1214: 
        !          1215: static bool check_address_object(ts_type_t ts_type, chunk_t object)
        !          1216: {
        !          1217:        switch (ts_type)
        !          1218:        {
        !          1219:                case TS_IPV4_ADDR_RANGE:
        !          1220:                        if (object.len > 5)
        !          1221:                        {
        !          1222:                                DBG1(DBG_ASN, "IPv4 address object is larger than 5 octets");
        !          1223:                                return FALSE;
        !          1224:                        }
        !          1225:                        break;
        !          1226:                case TS_IPV6_ADDR_RANGE:
        !          1227:                        if (object.len > 17)
        !          1228:                        {
        !          1229:                                DBG1(DBG_ASN, "IPv6 address object is larger than 17 octets");
        !          1230:                                return FALSE;
        !          1231:                        }
        !          1232:                        break;
        !          1233:                default:
        !          1234:                        DBG1(DBG_ASN, "unknown address family");
        !          1235:                        return FALSE;
        !          1236:        }
        !          1237:        if (object.len == 0)
        !          1238:        {
        !          1239:                DBG1(DBG_ASN, "An ASN.1 bit string must contain at least the "
        !          1240:                         "initial octet");
        !          1241:                return FALSE;
        !          1242:        }
        !          1243:        if (object.len == 1 && object.ptr[0] != 0)
        !          1244:        {
        !          1245:                DBG1(DBG_ASN, "An empty ASN.1 bit string must contain a zero "
        !          1246:                         "initial octet");
        !          1247:                return FALSE;
        !          1248:        }
        !          1249:        if (object.ptr[0] > 7)
        !          1250:        {
        !          1251:                DBG1(DBG_ASN, "number of unused bits is too large");
        !          1252:                return FALSE;
        !          1253:        }
        !          1254:        return TRUE;
        !          1255: }
        !          1256: 
        !          1257: static bool parse_ipAddrBlocks(chunk_t blob, int level0,
        !          1258:                                                           private_x509_cert_t *this)
        !          1259: {
        !          1260:        asn1_parser_t *parser;
        !          1261:        chunk_t object, min_object;
        !          1262:        ts_type_t ts_type = 0;
        !          1263:        traffic_selector_t *ts;
        !          1264:        int objectID;
        !          1265:        bool success = FALSE;
        !          1266: 
        !          1267:        parser = asn1_parser_create(ipAddrBlocksObjects, blob);
        !          1268:        parser->set_top_level(parser, level0);
        !          1269: 
        !          1270:        while (parser->iterate(parser, &objectID, &object))
        !          1271:        {
        !          1272:                switch (objectID)
        !          1273:                {
        !          1274:                        case IP_ADDR_BLOCKS_FAMILY:
        !          1275:                                ts_type = 0;
        !          1276:                                if (object.len == 2 && object.ptr[0] == 0)
        !          1277:                                {
        !          1278:                                        if (object.ptr[1] == 1)
        !          1279:                                        {
        !          1280:                                                ts_type = TS_IPV4_ADDR_RANGE;
        !          1281:                                        }
        !          1282:                                        else if (object.ptr[1] == 2)
        !          1283:                                        {
        !          1284:                                                ts_type = TS_IPV6_ADDR_RANGE;
        !          1285:                                        }
        !          1286:                                        else
        !          1287:                                        {
        !          1288:                                                break;
        !          1289:                                        }
        !          1290:                                        DBG2(DBG_ASN, "  %N", ts_type_name, ts_type);
        !          1291:                                }
        !          1292:                                break;
        !          1293:                        case IP_ADDR_BLOCKS_INHERIT:
        !          1294:                                DBG1(DBG_ASN, "inherit choice is not supported");
        !          1295:                                break;
        !          1296:                        case IP_ADDR_BLOCKS_PREFIX:
        !          1297:                                if (!check_address_object(ts_type, object))
        !          1298:                                {
        !          1299:                                        goto end;
        !          1300:                                }
        !          1301:                                ts = traffic_selector_create_from_rfc3779_format(ts_type,
        !          1302:                                                                                                        object, object);
        !          1303:                                DBG2(DBG_ASN, "  %R", ts);
        !          1304:                                this->ipAddrBlocks->insert_last(this->ipAddrBlocks, ts);
        !          1305:                                break;
        !          1306:                        case IP_ADDR_BLOCKS_MIN:
        !          1307:                                if (!check_address_object(ts_type, object))
        !          1308:                                {
        !          1309:                                        goto end;
        !          1310:                                }
        !          1311:                                min_object = object;
        !          1312:                                break;
        !          1313:                        case IP_ADDR_BLOCKS_MAX:
        !          1314:                                if (!check_address_object(ts_type, object))
        !          1315:                                {
        !          1316:                                        goto end;
        !          1317:                                }
        !          1318:                                ts = traffic_selector_create_from_rfc3779_format(ts_type,
        !          1319:                                                                                                        min_object, object);
        !          1320:                                DBG2(DBG_ASN, "  %R", ts);
        !          1321:                                this->ipAddrBlocks->insert_last(this->ipAddrBlocks, ts);
        !          1322:                                break;
        !          1323:                        default:
        !          1324:                                break;
        !          1325:                }
        !          1326:        }
        !          1327:        success = parser->success(parser);
        !          1328:        this->flags |= X509_IP_ADDR_BLOCKS;
        !          1329: 
        !          1330: end:
        !          1331:        parser->destroy(parser);
        !          1332: 
        !          1333:        return success;
        !          1334: }
        !          1335: 
        !          1336: /**
        !          1337:  * ASN.1 definition of an X.509v3 x509_cert
        !          1338:  */
        !          1339: static const asn1Object_t certObjects[] = {
        !          1340:        { 0, "x509",                                    ASN1_SEQUENCE,          ASN1_OBJ                        }, /*  0 */
        !          1341:        { 1,   "tbsCertificate",                ASN1_SEQUENCE,          ASN1_OBJ                        }, /*  1 */
        !          1342:        { 2,     "DEFAULT v1",                  ASN1_CONTEXT_C_0,       ASN1_DEF                        }, /*  2 */
        !          1343:        { 3,       "version",                   ASN1_INTEGER,           ASN1_BODY                       }, /*  3 */
        !          1344:        { 2,     "serialNumber",                ASN1_INTEGER,           ASN1_BODY                       }, /*  4 */
        !          1345:        { 2,     "signature",                   ASN1_EOC,                       ASN1_RAW                        }, /*  5 */
        !          1346:        { 2,     "issuer",                              ASN1_SEQUENCE,          ASN1_OBJ                        }, /*  6 */
        !          1347:        { 2,     "validity",                    ASN1_SEQUENCE,          ASN1_NONE                       }, /*  7 */
        !          1348:        { 3,       "notBefore",                 ASN1_EOC,                       ASN1_RAW                        }, /*  8 */
        !          1349:        { 3,       "notAfter",                  ASN1_EOC,                       ASN1_RAW                        }, /*  9 */
        !          1350:        { 2,     "subject",                             ASN1_SEQUENCE,          ASN1_OBJ                        }, /* 10 */
        !          1351:        { 2,     "subjectPublicKeyInfo",ASN1_SEQUENCE,          ASN1_RAW                        }, /* 11 */
        !          1352:        { 2,     "issuerUniqueID",              ASN1_CONTEXT_C_1,       ASN1_OPT                        }, /* 12 */
        !          1353:        { 2,     "end opt",                             ASN1_EOC,                       ASN1_END                        }, /* 13 */
        !          1354:        { 2,     "subjectUniqueID",             ASN1_CONTEXT_C_2,       ASN1_OPT                        }, /* 14 */
        !          1355:        { 2,     "end opt",                             ASN1_EOC,                       ASN1_END                        }, /* 15 */
        !          1356:        { 2,     "optional extensions", ASN1_CONTEXT_C_3,       ASN1_OPT                        }, /* 16 */
        !          1357:        { 3,       "extensions",                ASN1_SEQUENCE,          ASN1_LOOP                       }, /* 17 */
        !          1358:        { 4,         "extension",               ASN1_SEQUENCE,          ASN1_NONE                       }, /* 18 */
        !          1359:        { 5,           "extnID",                ASN1_OID,                       ASN1_BODY                       }, /* 19 */
        !          1360:        { 5,           "critical",              ASN1_BOOLEAN,           ASN1_DEF|ASN1_BODY      }, /* 20 */
        !          1361:        { 5,           "extnValue",             ASN1_OCTET_STRING,      ASN1_BODY                       }, /* 21 */
        !          1362:        { 3,       "end loop",                  ASN1_EOC,                       ASN1_END                        }, /* 22 */
        !          1363:        { 2,     "end opt",                             ASN1_EOC,                       ASN1_END                        }, /* 23 */
        !          1364:        { 1,   "signatureAlgorithm",    ASN1_EOC,                       ASN1_RAW                        }, /* 24 */
        !          1365:        { 1,   "signatureValue",                ASN1_BIT_STRING,        ASN1_BODY                       }, /* 25 */
        !          1366:        { 0, "exit",                                    ASN1_EOC,                       ASN1_EXIT                       }
        !          1367: };
        !          1368: #define X509_OBJ_TBS_CERTIFICATE                                1
        !          1369: #define X509_OBJ_VERSION                                                3
        !          1370: #define X509_OBJ_SERIAL_NUMBER                                  4
        !          1371: #define X509_OBJ_SIG_ALG                                                5
        !          1372: #define X509_OBJ_ISSUER                                                         6
        !          1373: #define X509_OBJ_NOT_BEFORE                                             8
        !          1374: #define X509_OBJ_NOT_AFTER                                              9
        !          1375: #define X509_OBJ_SUBJECT                                               10
        !          1376: #define X509_OBJ_SUBJECT_PUBLIC_KEY_INFO               11
        !          1377: #define X509_OBJ_OPTIONAL_EXTENSIONS                   16
        !          1378: #define X509_OBJ_EXTN_ID                                               19
        !          1379: #define X509_OBJ_CRITICAL                                              20
        !          1380: #define X509_OBJ_EXTN_VALUE                                            21
        !          1381: #define X509_OBJ_ALGORITHM                                             24
        !          1382: #define X509_OBJ_SIGNATURE                                             25
        !          1383: 
        !          1384: /**
        !          1385:  * Parses an X.509v3 certificate
        !          1386:  */
        !          1387: static bool parse_certificate(private_x509_cert_t *this)
        !          1388: {
        !          1389:        asn1_parser_t *parser;
        !          1390:        chunk_t object;
        !          1391:        int objectID;
        !          1392:        int extn_oid = OID_UNKNOWN;
        !          1393:        signature_params_t sig_alg = {};
        !          1394:        bool success = FALSE;
        !          1395:        bool critical = FALSE;
        !          1396: 
        !          1397:        parser = asn1_parser_create(certObjects, this->encoding);
        !          1398: 
        !          1399:        /* unless we see a keyUsage extension we are compliant with RFC 4945 */
        !          1400:        this->flags |= X509_IKE_COMPLIANT;
        !          1401: 
        !          1402:        while (parser->iterate(parser, &objectID, &object))
        !          1403:        {
        !          1404:                u_int level = parser->get_level(parser)+1;
        !          1405: 
        !          1406:                switch (objectID)
        !          1407:                {
        !          1408:                        case X509_OBJ_TBS_CERTIFICATE:
        !          1409:                                this->tbsCertificate = object;
        !          1410:                                break;
        !          1411:                        case X509_OBJ_VERSION:
        !          1412:                                this->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
        !          1413:                                if (this->version < 1 || this->version > 3)
        !          1414:                                {
        !          1415:                                        DBG1(DBG_ASN, "X.509v%d not supported", this->version);
        !          1416:                                        goto end;
        !          1417:                                }
        !          1418:                                else
        !          1419:                                {
        !          1420:                                        DBG2(DBG_ASN, "  X.509v%d", this->version);
        !          1421:                                }
        !          1422:                                break;
        !          1423:                        case X509_OBJ_SERIAL_NUMBER:
        !          1424:                                this->serialNumber = object;
        !          1425:                                break;
        !          1426:                        case X509_OBJ_SIG_ALG:
        !          1427:                                if (!signature_params_parse(object, level, &sig_alg))
        !          1428:                                {
        !          1429:                                        DBG1(DBG_ASN, "  unable to parse signature algorithm");
        !          1430:                                        goto end;
        !          1431:                                }
        !          1432:                                break;
        !          1433:                        case X509_OBJ_ISSUER:
        !          1434:                                this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
        !          1435:                                DBG2(DBG_ASN, "  '%Y'", this->issuer);
        !          1436:                                break;
        !          1437:                        case X509_OBJ_NOT_BEFORE:
        !          1438:                                this->notBefore = asn1_parse_time(object, level);
        !          1439:                                break;
        !          1440:                        case X509_OBJ_NOT_AFTER:
        !          1441:                                this->notAfter = asn1_parse_time(object, level);
        !          1442:                                break;
        !          1443:                        case X509_OBJ_SUBJECT:
        !          1444:                                this->subject = identification_create_from_encoding(ID_DER_ASN1_DN, object);
        !          1445:                                DBG2(DBG_ASN, "  '%Y'", this->subject);
        !          1446:                                break;
        !          1447:                        case X509_OBJ_SUBJECT_PUBLIC_KEY_INFO:
        !          1448:                                DBG2(DBG_ASN, "-- > --");
        !          1449:                                this->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
        !          1450:                                                KEY_ANY, BUILD_BLOB_ASN1_DER, object, BUILD_END);
        !          1451:                                DBG2(DBG_ASN, "-- < --");
        !          1452:                                if (this->public_key == NULL)
        !          1453:                                {
        !          1454:                                        goto end;
        !          1455:                                }
        !          1456:                                break;
        !          1457:                        case X509_OBJ_OPTIONAL_EXTENSIONS:
        !          1458:                                if (this->version != 3)
        !          1459:                                {
        !          1460:                                        DBG1(DBG_ASN, "Only X.509v3 certificates have extensions");
        !          1461:                                        goto end;
        !          1462:                                }
        !          1463:                                break;
        !          1464:                        case X509_OBJ_EXTN_ID:
        !          1465:                                extn_oid = asn1_known_oid(object);
        !          1466:                                break;
        !          1467:                        case X509_OBJ_CRITICAL:
        !          1468:                                critical = object.len && *object.ptr;
        !          1469:                                DBG2(DBG_ASN, "  %s", critical ? "TRUE" : "FALSE");
        !          1470:                                break;
        !          1471:                        case X509_OBJ_EXTN_VALUE:
        !          1472:                        {
        !          1473:                                switch (extn_oid)
        !          1474:                                {
        !          1475:                                        case OID_SUBJECT_KEY_ID:
        !          1476:                                                if (!asn1_parse_simple_object(&object, ASN1_OCTET_STRING,
        !          1477:                                                                                                          level, "keyIdentifier"))
        !          1478:                                                {
        !          1479:                                                        goto end;
        !          1480:                                                }
        !          1481:                                                this->subjectKeyIdentifier = object;
        !          1482:                                                break;
        !          1483:                                        case OID_SUBJECT_ALT_NAME:
        !          1484:                                                if (!x509_parse_generalNames(object, level, FALSE,
        !          1485:                                                                                                         this->subjectAltNames))
        !          1486:                                                {
        !          1487:                                                        goto end;
        !          1488:                                                }
        !          1489:                                                break;
        !          1490:                                        case OID_BASIC_CONSTRAINTS:
        !          1491:                                                if (!parse_basicConstraints(object, level, this))
        !          1492:                                                {
        !          1493:                                                        goto end;
        !          1494:                                                }
        !          1495:                                                break;
        !          1496:                                        case OID_CRL_DISTRIBUTION_POINTS:
        !          1497:                                                if (!x509_parse_crlDistributionPoints(object, level,
        !          1498:                                                                                                                          this->crl_uris))
        !          1499:                                                {
        !          1500:                                                        goto end;
        !          1501:                                                }
        !          1502:                                                break;
        !          1503:                                        case OID_AUTHORITY_KEY_ID:
        !          1504:                                                chunk_free(&this->authKeyIdentifier);
        !          1505:                                                this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(
        !          1506:                                                                        object, level, &this->authKeySerialNumber);
        !          1507:                                                break;
        !          1508:                                        case OID_AUTHORITY_INFO_ACCESS:
        !          1509:                                                if (!parse_authorityInfoAccess(object, level, this))
        !          1510:                                                {
        !          1511:                                                        goto end;
        !          1512:                                                }
        !          1513:                                                break;
        !          1514:                                        case OID_KEY_USAGE:
        !          1515:                                                parse_keyUsage(object, this);
        !          1516:                                                break;
        !          1517:                                        case OID_EXTENDED_KEY_USAGE:
        !          1518:                                                if (!parse_extendedKeyUsage(object, level, this))
        !          1519:                                                {
        !          1520:                                                        goto end;
        !          1521:                                                }
        !          1522:                                                break;
        !          1523:                                        case OID_IP_ADDR_BLOCKS:
        !          1524:                                                if (!parse_ipAddrBlocks(object, level, this))
        !          1525:                                                {
        !          1526:                                                        goto end;
        !          1527:                                                }
        !          1528:                                                break;
        !          1529:                                        case OID_NAME_CONSTRAINTS:
        !          1530:                                                if (!parse_nameConstraints(object, level, this))
        !          1531:                                                {
        !          1532:                                                        goto end;
        !          1533:                                                }
        !          1534:                                                break;
        !          1535:                                        case OID_CERTIFICATE_POLICIES:
        !          1536:                                                if (!parse_certificatePolicies(object, level, this))
        !          1537:                                                {
        !          1538:                                                        goto end;
        !          1539:                                                }
        !          1540:                                                break;
        !          1541:                                        case OID_POLICY_MAPPINGS:
        !          1542:                                                if (!parse_policyMappings(object, level, this))
        !          1543:                                                {
        !          1544:                                                        goto end;
        !          1545:                                                }
        !          1546:                                                break;
        !          1547:                                        case OID_POLICY_CONSTRAINTS:
        !          1548:                                                if (!parse_policyConstraints(object, level, this))
        !          1549:                                                {
        !          1550:                                                        goto end;
        !          1551:                                                }
        !          1552:                                                break;
        !          1553:                                        case OID_INHIBIT_ANY_POLICY:
        !          1554:                                                if (!asn1_parse_simple_object(&object, ASN1_INTEGER,
        !          1555:                                                                                                          level, "inhibitAnyPolicy"))
        !          1556:                                                {
        !          1557:                                                        goto end;
        !          1558:                                                }
        !          1559:                                                this->inhibit_any = parse_constraint(object);
        !          1560:                                                break;
        !          1561:                                        case OID_NS_REVOCATION_URL:
        !          1562:                                        case OID_NS_CA_REVOCATION_URL:
        !          1563:                                        case OID_NS_CA_POLICY_URL:
        !          1564:                                        case OID_NS_COMMENT:
        !          1565:                                                if (!asn1_parse_simple_object(&object, ASN1_IA5STRING,
        !          1566:                                                                                        level, oid_names[extn_oid].name))
        !          1567:                                                {
        !          1568:                                                        goto end;
        !          1569:                                                }
        !          1570:                                                break;
        !          1571:                                        default:
        !          1572:                                                if (critical && lib->settings->get_bool(lib->settings,
        !          1573:                                                        "%s.x509.enforce_critical", TRUE, lib->ns))
        !          1574:                                                {
        !          1575:                                                        DBG1(DBG_ASN, "critical '%s' extension not supported",
        !          1576:                                                                 (extn_oid == OID_UNKNOWN) ? "unknown" :
        !          1577:                                                                 (char*)oid_names[extn_oid].name);
        !          1578:                                                        goto end;
        !          1579:                                                }
        !          1580:                                                break;
        !          1581:                                }
        !          1582:                                break;
        !          1583:                        }
        !          1584:                        case X509_OBJ_ALGORITHM:
        !          1585:                                INIT(this->scheme);
        !          1586:                                if (!signature_params_parse(object, level, this->scheme))
        !          1587:                                {
        !          1588:                                        DBG1(DBG_ASN, "  unable to parse signature algorithm");
        !          1589:                                        goto end;
        !          1590:                                }
        !          1591:                                if (!signature_params_equal(this->scheme, &sig_alg))
        !          1592:                                {
        !          1593:                                        DBG1(DBG_ASN, "  signature algorithms do not agree");
        !          1594:                                        goto end;
        !          1595:                                }
        !          1596:                                break;
        !          1597:                        case X509_OBJ_SIGNATURE:
        !          1598:                                this->signature = chunk_skip(object, 1);
        !          1599:                                break;
        !          1600:                        default:
        !          1601:                                break;
        !          1602:                }
        !          1603:        }
        !          1604:        success = parser->success(parser);
        !          1605: 
        !          1606: end:
        !          1607:        parser->destroy(parser);
        !          1608:        signature_params_clear(&sig_alg);
        !          1609:        if (success)
        !          1610:        {
        !          1611:                hasher_t *hasher;
        !          1612: 
        !          1613:                /* check if the certificate is self-signed */
        !          1614:                if (this->public.interface.interface.issued_by(
        !          1615:                                                                                        &this->public.interface.interface,
        !          1616:                                                                                        &this->public.interface.interface,
        !          1617:                                                                                        NULL))
        !          1618:                {
        !          1619:                        this->flags |= X509_SELF_SIGNED;
        !          1620:                }
        !          1621:                /* create certificate hash */
        !          1622:                hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
        !          1623:                if (!hasher ||
        !          1624:                        !hasher->allocate_hash(hasher, this->encoding, &this->encoding_hash))
        !          1625:                {
        !          1626:                        DESTROY_IF(hasher);
        !          1627:                        DBG1(DBG_ASN, "  unable to create hash of certificate, SHA1 not supported");
        !          1628:                        return FALSE;
        !          1629:                }
        !          1630:                hasher->destroy(hasher);
        !          1631:        }
        !          1632:        return success;
        !          1633: }
        !          1634: 
        !          1635: METHOD(certificate_t, get_type, certificate_type_t,
        !          1636:        private_x509_cert_t *this)
        !          1637: {
        !          1638:        return CERT_X509;
        !          1639: }
        !          1640: 
        !          1641: METHOD(certificate_t, get_subject, identification_t*,
        !          1642:        private_x509_cert_t *this)
        !          1643: {
        !          1644:        return this->subject;
        !          1645: }
        !          1646: 
        !          1647: METHOD(certificate_t, get_issuer, identification_t*,
        !          1648:        private_x509_cert_t *this)
        !          1649: {
        !          1650:        return this->issuer;
        !          1651: }
        !          1652: 
        !          1653: METHOD(certificate_t, has_subject, id_match_t,
        !          1654:        private_x509_cert_t *this, identification_t *subject)
        !          1655: {
        !          1656:        identification_t *current;
        !          1657:        enumerator_t *enumerator;
        !          1658:        id_match_t match, best;
        !          1659:        chunk_t encoding;
        !          1660: 
        !          1661:        if (subject->get_type(subject) == ID_KEY_ID)
        !          1662:        {
        !          1663:                encoding = subject->get_encoding(subject);
        !          1664: 
        !          1665:                if (this->encoding_hash.len &&
        !          1666:                        chunk_equals(this->encoding_hash, encoding))
        !          1667:                {
        !          1668:                        return ID_MATCH_PERFECT;
        !          1669:                }
        !          1670:                if (this->subjectKeyIdentifier.len &&
        !          1671:                        chunk_equals(this->subjectKeyIdentifier, encoding))
        !          1672:                {
        !          1673:                        return ID_MATCH_PERFECT;
        !          1674:                }
        !          1675:                if (this->public_key &&
        !          1676:                        this->public_key->has_fingerprint(this->public_key, encoding))
        !          1677:                {
        !          1678:                        return ID_MATCH_PERFECT;
        !          1679:                }
        !          1680:                if (chunk_equals(this->serialNumber, encoding))
        !          1681:                {
        !          1682:                        return ID_MATCH_PERFECT;
        !          1683:                }
        !          1684:        }
        !          1685:        best = this->subject->matches(this->subject, subject);
        !          1686:        enumerator = this->subjectAltNames->create_enumerator(this->subjectAltNames);
        !          1687:        while (enumerator->enumerate(enumerator, &current))
        !          1688:        {
        !          1689:                match = current->matches(current, subject);
        !          1690:                if (match > best)
        !          1691:                {
        !          1692:                        best = match;
        !          1693:                }
        !          1694:        }
        !          1695:        enumerator->destroy(enumerator);
        !          1696:        return best;
        !          1697: }
        !          1698: 
        !          1699: METHOD(certificate_t, has_issuer, id_match_t,
        !          1700:        private_x509_cert_t *this, identification_t *issuer)
        !          1701: {
        !          1702:        /* issuerAltNames currently not supported */
        !          1703:        return this->issuer->matches(this->issuer, issuer);
        !          1704: }
        !          1705: 
        !          1706: METHOD(certificate_t, issued_by, bool,
        !          1707:        private_x509_cert_t *this, certificate_t *issuer,
        !          1708:        signature_params_t **scheme)
        !          1709: {
        !          1710:        public_key_t *key;
        !          1711:        bool valid;
        !          1712:        x509_t *x509 = (x509_t*)issuer;
        !          1713: 
        !          1714:        if (&this->public.interface.interface == issuer)
        !          1715:        {
        !          1716:                if (this->flags & X509_SELF_SIGNED)
        !          1717:                {
        !          1718:                        if (scheme)
        !          1719:                        {
        !          1720:                                *scheme = signature_params_clone(this->scheme);
        !          1721:                        }
        !          1722:                        return TRUE;
        !          1723:                }
        !          1724:        }
        !          1725:        else
        !          1726:        {
        !          1727:                if (issuer->get_type(issuer) != CERT_X509)
        !          1728:                {
        !          1729:                        return FALSE;
        !          1730:                }
        !          1731:                if (!(x509->get_flags(x509) & X509_CA))
        !          1732:                {
        !          1733:                        return FALSE;
        !          1734:                }
        !          1735:        }
        !          1736:        if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
        !          1737:        {
        !          1738:                return FALSE;
        !          1739:        }
        !          1740: 
        !          1741:        /* get the public key of the issuer */
        !          1742:        key = issuer->get_public_key(issuer);
        !          1743:        if (!key)
        !          1744:        {
        !          1745:                return FALSE;
        !          1746:        }
        !          1747:        valid = key->verify(key, this->scheme->scheme, this->scheme->params,
        !          1748:                                                this->tbsCertificate, this->signature);
        !          1749:        key->destroy(key);
        !          1750:        if (valid && scheme)
        !          1751:        {
        !          1752:                *scheme = signature_params_clone(this->scheme);
        !          1753:        }
        !          1754:        return valid;
        !          1755: }
        !          1756: 
        !          1757: METHOD(certificate_t, get_public_key, public_key_t*,
        !          1758:        private_x509_cert_t *this)
        !          1759: {
        !          1760:        this->public_key->get_ref(this->public_key);
        !          1761:        return this->public_key;
        !          1762: }
        !          1763: 
        !          1764: METHOD(certificate_t, get_ref, certificate_t*,
        !          1765:        private_x509_cert_t *this)
        !          1766: {
        !          1767:        ref_get(&this->ref);
        !          1768:        return &this->public.interface.interface;
        !          1769: }
        !          1770: 
        !          1771: METHOD(certificate_t, get_validity, bool,
        !          1772:        private_x509_cert_t *this, time_t *when, time_t *not_before,
        !          1773:        time_t *not_after)
        !          1774: {
        !          1775:        time_t t = when ? *when : time(NULL);
        !          1776: 
        !          1777:        if (not_before)
        !          1778:        {
        !          1779:                *not_before = this->notBefore;
        !          1780:        }
        !          1781:        if (not_after)
        !          1782:        {
        !          1783:                *not_after = this->notAfter;
        !          1784:        }
        !          1785:        return (t >= this->notBefore && t <= this->notAfter);
        !          1786: }
        !          1787: 
        !          1788: METHOD(certificate_t, get_encoding, bool,
        !          1789:        private_x509_cert_t *this, cred_encoding_type_t type, chunk_t *encoding)
        !          1790: {
        !          1791:        if (type == CERT_ASN1_DER)
        !          1792:        {
        !          1793:                *encoding = chunk_clone(this->encoding);
        !          1794:                return TRUE;
        !          1795:        }
        !          1796:        return lib->encoding->encode(lib->encoding, type, NULL, encoding,
        !          1797:                                                CRED_PART_X509_ASN1_DER, this->encoding, CRED_PART_END);
        !          1798: }
        !          1799: 
        !          1800: METHOD(certificate_t, equals, bool,
        !          1801:        private_x509_cert_t *this, certificate_t *other)
        !          1802: {
        !          1803:        chunk_t encoding;
        !          1804:        bool equal;
        !          1805: 
        !          1806:        if (this == (private_x509_cert_t*)other)
        !          1807:        {
        !          1808:                return TRUE;
        !          1809:        }
        !          1810:        if (other->get_type(other) != CERT_X509)
        !          1811:        {
        !          1812:                return FALSE;
        !          1813:        }
        !          1814:        if (other->equals == (void*)equals)
        !          1815:        {       /* skip allocation if we have the same implementation */
        !          1816:                return chunk_equals(this->encoding, ((private_x509_cert_t*)other)->encoding);
        !          1817:        }
        !          1818:        if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
        !          1819:        {
        !          1820:                return FALSE;
        !          1821:        }
        !          1822:        equal = chunk_equals(this->encoding, encoding);
        !          1823:        free(encoding.ptr);
        !          1824:        return equal;
        !          1825: }
        !          1826: 
        !          1827: METHOD(x509_t, get_flags, x509_flag_t,
        !          1828:        private_x509_cert_t *this)
        !          1829: {
        !          1830:        return this->flags;
        !          1831: }
        !          1832: 
        !          1833: METHOD(x509_t, get_serial, chunk_t,
        !          1834:        private_x509_cert_t *this)
        !          1835: {
        !          1836:        return this->serialNumber;
        !          1837: }
        !          1838: 
        !          1839: METHOD(x509_t, get_subjectKeyIdentifier, chunk_t,
        !          1840:        private_x509_cert_t *this)
        !          1841: {
        !          1842:        if (this->subjectKeyIdentifier.ptr)
        !          1843:        {
        !          1844:                return this->subjectKeyIdentifier;
        !          1845:        }
        !          1846:        else
        !          1847:        {
        !          1848:                chunk_t fingerprint;
        !          1849: 
        !          1850:                if (this->public_key->get_fingerprint(this->public_key,
        !          1851:                                                                        KEYID_PUBKEY_SHA1, &fingerprint))
        !          1852:                {
        !          1853:                        return fingerprint;
        !          1854:                }
        !          1855:                else
        !          1856:                {
        !          1857:                        return chunk_empty;
        !          1858:                }
        !          1859:        }
        !          1860: }
        !          1861: 
        !          1862: METHOD(x509_t, get_authKeyIdentifier, chunk_t,
        !          1863:        private_x509_cert_t *this)
        !          1864: {
        !          1865:        return this->authKeyIdentifier;
        !          1866: }
        !          1867: 
        !          1868: METHOD(x509_t, get_constraint, u_int,
        !          1869:        private_x509_cert_t *this, x509_constraint_t type)
        !          1870: {
        !          1871:        switch (type)
        !          1872:        {
        !          1873:                case X509_PATH_LEN:
        !          1874:                        return this->pathLenConstraint;
        !          1875:                case X509_REQUIRE_EXPLICIT_POLICY:
        !          1876:                        return this->require_explicit;
        !          1877:                case X509_INHIBIT_POLICY_MAPPING:
        !          1878:                        return this->inhibit_mapping;
        !          1879:                case X509_INHIBIT_ANY_POLICY:
        !          1880:                        return this->inhibit_any;
        !          1881:                default:
        !          1882:                        return X509_NO_CONSTRAINT;
        !          1883:        }
        !          1884: }
        !          1885: 
        !          1886: METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
        !          1887:        private_x509_cert_t *this)
        !          1888: {
        !          1889:        return this->subjectAltNames->create_enumerator(this->subjectAltNames);
        !          1890: }
        !          1891: 
        !          1892: METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
        !          1893:        private_x509_cert_t *this)
        !          1894: {
        !          1895:        return this->ocsp_uris->create_enumerator(this->ocsp_uris);
        !          1896: }
        !          1897: 
        !          1898: METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*,
        !          1899:        private_x509_cert_t *this)
        !          1900: {
        !          1901:        return this->crl_uris->create_enumerator(this->crl_uris);
        !          1902: }
        !          1903: 
        !          1904: METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
        !          1905:        private_x509_cert_t *this)
        !          1906: {
        !          1907:        return this->ipAddrBlocks->create_enumerator(this->ipAddrBlocks);
        !          1908: }
        !          1909: 
        !          1910: METHOD(x509_t, create_name_constraint_enumerator, enumerator_t*,
        !          1911:        private_x509_cert_t *this, bool perm)
        !          1912: {
        !          1913:        if (perm)
        !          1914:        {
        !          1915:                return this->permitted_names->create_enumerator(this->permitted_names);
        !          1916:        }
        !          1917:        return this->excluded_names->create_enumerator(this->excluded_names);
        !          1918: }
        !          1919: 
        !          1920: METHOD(x509_t, create_cert_policy_enumerator, enumerator_t*,
        !          1921:        private_x509_cert_t *this)
        !          1922: {
        !          1923:        return this->cert_policies->create_enumerator(this->cert_policies);
        !          1924: }
        !          1925: 
        !          1926: METHOD(x509_t, create_policy_mapping_enumerator, enumerator_t*,
        !          1927:        private_x509_cert_t *this)
        !          1928: {
        !          1929:        return this->policy_mappings->create_enumerator(this->policy_mappings);
        !          1930: }
        !          1931: 
        !          1932: METHOD(certificate_t, destroy, void,
        !          1933:        private_x509_cert_t *this)
        !          1934: {
        !          1935:        if (ref_put(&this->ref))
        !          1936:        {
        !          1937:                this->subjectAltNames->destroy_offset(this->subjectAltNames,
        !          1938:                                                                        offsetof(identification_t, destroy));
        !          1939:                this->crl_uris->destroy_function(this->crl_uris,
        !          1940:                                                                                 (void*)x509_cdp_destroy);
        !          1941:                this->ocsp_uris->destroy_function(this->ocsp_uris, free);
        !          1942:                this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks,
        !          1943:                                                                                offsetof(traffic_selector_t, destroy));
        !          1944:                this->permitted_names->destroy_offset(this->permitted_names,
        !          1945:                                                                                offsetof(identification_t, destroy));
        !          1946:                this->excluded_names->destroy_offset(this->excluded_names,
        !          1947:                                                                                offsetof(identification_t, destroy));
        !          1948:                this->cert_policies->destroy_function(this->cert_policies,
        !          1949:                                                                                          (void*)cert_policy_destroy);
        !          1950:                this->policy_mappings->destroy_function(this->policy_mappings,
        !          1951:                                                                                          (void*)policy_mapping_destroy);
        !          1952:                signature_params_destroy(this->scheme);
        !          1953:                DESTROY_IF(this->issuer);
        !          1954:                DESTROY_IF(this->subject);
        !          1955:                DESTROY_IF(this->public_key);
        !          1956:                chunk_free(&this->authKeyIdentifier);
        !          1957:                chunk_free(&this->encoding);
        !          1958:                chunk_free(&this->encoding_hash);
        !          1959:                chunk_free(&this->critical_extension_oid);
        !          1960:                if (!this->parsed)
        !          1961:                {       /* only parsed certificates point these fields to "encoded" */
        !          1962:                        chunk_free(&this->signature);
        !          1963:                        chunk_free(&this->serialNumber);
        !          1964:                        chunk_free(&this->tbsCertificate);
        !          1965:                }
        !          1966:                free(this);
        !          1967:        }
        !          1968: }
        !          1969: 
        !          1970: /**
        !          1971:  * create an empty but initialized X.509 certificate
        !          1972:  */
        !          1973: static private_x509_cert_t* create_empty(void)
        !          1974: {
        !          1975:        private_x509_cert_t *this;
        !          1976: 
        !          1977:        INIT(this,
        !          1978:                .public = {
        !          1979:                        .interface = {
        !          1980:                                .interface = {
        !          1981:                                        .get_type = _get_type,
        !          1982:                                        .get_subject = _get_subject,
        !          1983:                                        .get_issuer = _get_issuer,
        !          1984:                                        .has_subject = _has_subject,
        !          1985:                                        .has_issuer = _has_issuer,
        !          1986:                                        .issued_by = _issued_by,
        !          1987:                                        .get_public_key = _get_public_key,
        !          1988:                                        .get_validity = _get_validity,
        !          1989:                                        .get_encoding = _get_encoding,
        !          1990:                                        .equals = _equals,
        !          1991:                                        .get_ref = _get_ref,
        !          1992:                                        .destroy = _destroy,
        !          1993:                                },
        !          1994:                                .get_flags = _get_flags,
        !          1995:                                .get_serial = _get_serial,
        !          1996:                                .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
        !          1997:                                .get_authKeyIdentifier = _get_authKeyIdentifier,
        !          1998:                                .get_constraint = _get_constraint,
        !          1999:                                .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
        !          2000:                                .create_crl_uri_enumerator = _create_crl_uri_enumerator,
        !          2001:                                .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
        !          2002:                                .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
        !          2003:                                .create_name_constraint_enumerator = _create_name_constraint_enumerator,
        !          2004:                                .create_cert_policy_enumerator = _create_cert_policy_enumerator,
        !          2005:                                .create_policy_mapping_enumerator = _create_policy_mapping_enumerator,
        !          2006:                        },
        !          2007:                },
        !          2008:                .version = 1,
        !          2009:                .subjectAltNames = linked_list_create(),
        !          2010:                .crl_uris = linked_list_create(),
        !          2011:                .ocsp_uris = linked_list_create(),
        !          2012:                .ipAddrBlocks = linked_list_create(),
        !          2013:                .permitted_names = linked_list_create(),
        !          2014:                .excluded_names = linked_list_create(),
        !          2015:                .cert_policies = linked_list_create(),
        !          2016:                .policy_mappings = linked_list_create(),
        !          2017:                .pathLenConstraint = X509_NO_CONSTRAINT,
        !          2018:                .require_explicit = X509_NO_CONSTRAINT,
        !          2019:                .inhibit_mapping = X509_NO_CONSTRAINT,
        !          2020:                .inhibit_any = X509_NO_CONSTRAINT,
        !          2021:                .ref = 1,
        !          2022:        );
        !          2023:        return this;
        !          2024: }
        !          2025: 
        !          2026: /**
        !          2027:  * Build a generalName from an id
        !          2028:  */
        !          2029: chunk_t build_generalName(identification_t *id)
        !          2030: {
        !          2031:        int context;
        !          2032: 
        !          2033:        switch (id->get_type(id))
        !          2034:        {
        !          2035:                case ID_DER_ASN1_GN:
        !          2036:                        return chunk_clone(id->get_encoding(id));
        !          2037:                case ID_RFC822_ADDR:
        !          2038:                        context = ASN1_CONTEXT_S_1;
        !          2039:                        break;
        !          2040:                case ID_FQDN:
        !          2041:                        context = ASN1_CONTEXT_S_2;
        !          2042:                        break;
        !          2043:                case ID_DER_ASN1_DN:
        !          2044:                        context = ASN1_CONTEXT_C_4;
        !          2045:                        break;
        !          2046:                case ID_IPV4_ADDR:
        !          2047:                case ID_IPV6_ADDR:
        !          2048:                        context = ASN1_CONTEXT_S_7;
        !          2049:                        break;
        !          2050:                default:
        !          2051:                        DBG1(DBG_ASN, "encoding %N as generalName not supported",
        !          2052:                                 id_type_names, id->get_type(id));
        !          2053:                        return chunk_empty;
        !          2054:        }
        !          2055:        return asn1_wrap(context, "c", id->get_encoding(id));
        !          2056: }
        !          2057: 
        !          2058: /**
        !          2059:  * Encode a linked list of subjectAltNames
        !          2060:  */
        !          2061: chunk_t x509_build_subjectAltNames(linked_list_t *list)
        !          2062: {
        !          2063:        chunk_t subjectAltNames = chunk_empty, name;
        !          2064:        enumerator_t *enumerator;
        !          2065:        identification_t *id;
        !          2066: 
        !          2067:        if (list->get_count(list) == 0)
        !          2068:        {
        !          2069:                return chunk_empty;
        !          2070:        }
        !          2071: 
        !          2072:        enumerator = list->create_enumerator(list);
        !          2073:        while (enumerator->enumerate(enumerator, &id))
        !          2074:        {
        !          2075:                name = build_generalName(id);
        !          2076:                subjectAltNames = chunk_cat("mm", subjectAltNames, name);
        !          2077:        }
        !          2078:        enumerator->destroy(enumerator);
        !          2079: 
        !          2080:        return asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2081:                                                asn1_build_known_oid(OID_SUBJECT_ALT_NAME),
        !          2082:                                                asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2083:                                                        asn1_wrap(ASN1_SEQUENCE, "m", subjectAltNames)
        !          2084:                                                )
        !          2085:                                         );
        !          2086: }
        !          2087: 
        !          2088: /**
        !          2089:  * Encode CRL distribution points extension from a x509_cdp_t list
        !          2090:  */
        !          2091: chunk_t x509_build_crlDistributionPoints(linked_list_t *list, int extn)
        !          2092: {
        !          2093:        chunk_t crlDistributionPoints = chunk_empty;
        !          2094:        enumerator_t *enumerator;
        !          2095:        x509_cdp_t *cdp;
        !          2096: 
        !          2097:        if (list->get_count(list) == 0)
        !          2098:        {
        !          2099:                return chunk_empty;
        !          2100:        }
        !          2101: 
        !          2102:        enumerator = list->create_enumerator(list);
        !          2103:        while (enumerator->enumerate(enumerator, &cdp))
        !          2104:        {
        !          2105:                chunk_t distributionPoint, crlIssuer = chunk_empty;
        !          2106: 
        !          2107:                if (cdp->issuer)
        !          2108:                {
        !          2109:                        crlIssuer = asn1_wrap(ASN1_CONTEXT_C_2, "m",
        !          2110:                                                        build_generalName(cdp->issuer));
        !          2111:                }
        !          2112:                distributionPoint = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2113:                                        asn1_wrap(ASN1_CONTEXT_C_0, "m",
        !          2114:                                                asn1_wrap(ASN1_CONTEXT_C_0, "m",
        !          2115:                                                        asn1_wrap(ASN1_CONTEXT_S_6, "c",
        !          2116:                                                                chunk_create(cdp->uri, strlen(cdp->uri))))),
        !          2117:                                        crlIssuer);
        !          2118:                crlDistributionPoints = chunk_cat("mm", crlDistributionPoints,
        !          2119:                                                                                  distributionPoint);
        !          2120:        }
        !          2121:        enumerator->destroy(enumerator);
        !          2122: 
        !          2123:        return asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2124:                                asn1_build_known_oid(extn),
        !          2125:                                asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2126:                                        asn1_wrap(ASN1_SEQUENCE, "m", crlDistributionPoints)));
        !          2127: }
        !          2128: 
        !          2129: static chunk_t generate_ts(traffic_selector_t *ts)
        !          2130: {
        !          2131:        chunk_t from, to;
        !          2132:        uint8_t minbits = 0, maxbits = 0, unused;
        !          2133:        host_t *net;
        !          2134:        int bit, byte;
        !          2135: 
        !          2136:        if (ts->to_subnet(ts, &net, &minbits))
        !          2137:        {
        !          2138:                unused = round_up(minbits, BITS_PER_BYTE) - minbits;
        !          2139:                from = asn1_wrap(ASN1_BIT_STRING, "m",
        !          2140:                        chunk_cat("cc", chunk_from_thing(unused),
        !          2141:                                                        chunk_create(net->get_address(net).ptr,
        !          2142:                                                                                 (minbits + unused) / BITS_PER_BYTE)));
        !          2143:                net->destroy(net);
        !          2144:                return from;
        !          2145:        }
        !          2146:        net->destroy(net);
        !          2147: 
        !          2148:        from = ts->get_from_address(ts);
        !          2149:        for (byte = from.len - 1; byte >= 0; byte--)
        !          2150:        {
        !          2151:                if (from.ptr[byte] != 0)
        !          2152:                {
        !          2153:                        minbits = byte * BITS_PER_BYTE + BITS_PER_BYTE;
        !          2154:                        for (bit = 0; bit < BITS_PER_BYTE; bit++)
        !          2155:                        {
        !          2156:                                if (from.ptr[byte] & 1 << bit)
        !          2157:                                {
        !          2158:                                        break;
        !          2159:                                }
        !          2160:                                minbits--;
        !          2161:                        }
        !          2162:                        break;
        !          2163:                }
        !          2164:        }
        !          2165:        to = ts->get_to_address(ts);
        !          2166:        for (byte = to.len - 1; byte >= 0; byte--)
        !          2167:        {
        !          2168:                if (to.ptr[byte] != 0xFF)
        !          2169:                {
        !          2170:                        maxbits = byte * BITS_PER_BYTE + BITS_PER_BYTE;
        !          2171:                        for (bit = 0; bit < BITS_PER_BYTE; bit++)
        !          2172:                        {
        !          2173:                                if ((to.ptr[byte] & 1 << bit) == 0)
        !          2174:                                {
        !          2175:                                        break;
        !          2176:                                }
        !          2177:                                maxbits--;
        !          2178:                        }
        !          2179:                        break;
        !          2180:                }
        !          2181:        }
        !          2182:        unused = round_up(minbits, BITS_PER_BYTE) - minbits;
        !          2183:        from = asn1_wrap(ASN1_BIT_STRING, "m",
        !          2184:                        chunk_cat("cc", chunk_from_thing(unused),
        !          2185:                                                        chunk_create(from.ptr,
        !          2186:                                                                                 (minbits + unused) / BITS_PER_BYTE)));
        !          2187:        unused = round_up(maxbits, BITS_PER_BYTE) - maxbits;
        !          2188:        to = asn1_wrap(ASN1_BIT_STRING, "m",
        !          2189:                        chunk_cat("cc", chunk_from_thing(unused),
        !          2190:                                                        chunk_create(to.ptr,
        !          2191:                                                                                 (maxbits + unused) / BITS_PER_BYTE)));
        !          2192:        return asn1_wrap(ASN1_SEQUENCE, "mm", from, to);
        !          2193: }
        !          2194: 
        !          2195: /**
        !          2196:  * Generate and sign a new certificate
        !          2197:  */
        !          2198: static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
        !          2199:                                         private_key_t *sign_key, int digest_alg)
        !          2200: {
        !          2201:        const chunk_t keyUsageCrlSign = chunk_from_chars(0x01, 0x02);
        !          2202:        const chunk_t keyUsageCertSignCrlSign = chunk_from_chars(0x01, 0x06);
        !          2203:        chunk_t extensions = chunk_empty, extendedKeyUsage = chunk_empty;
        !          2204:        chunk_t serverAuth = chunk_empty, clientAuth = chunk_empty;
        !          2205:        chunk_t ocspSigning = chunk_empty, certPolicies = chunk_empty;
        !          2206:        chunk_t basicConstraints = chunk_empty, nameConstraints = chunk_empty;
        !          2207:        chunk_t keyUsage = chunk_empty, keyUsageBits = chunk_empty;
        !          2208:        chunk_t subjectAltNames = chunk_empty, policyMappings = chunk_empty;
        !          2209:        chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty;
        !          2210:        chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty;
        !          2211:        chunk_t policyConstraints = chunk_empty, inhibitAnyPolicy = chunk_empty;
        !          2212:        chunk_t ikeIntermediate = chunk_empty, msSmartcardLogon = chunk_empty;
        !          2213:        chunk_t ipAddrBlocks = chunk_empty, sig_scheme = chunk_empty;
        !          2214:        chunk_t criticalExtension = chunk_empty;
        !          2215:        identification_t *issuer, *subject;
        !          2216:        chunk_t key_info;
        !          2217:        hasher_t *hasher;
        !          2218:        enumerator_t *enumerator;
        !          2219:        char *uri;
        !          2220: 
        !          2221:        subject = cert->subject;
        !          2222:        if (sign_cert)
        !          2223:        {
        !          2224:                issuer = sign_cert->get_subject(sign_cert);
        !          2225:                if (!cert->public_key)
        !          2226:                {
        !          2227:                        return FALSE;
        !          2228:                }
        !          2229:        }
        !          2230:        else
        !          2231:        {       /* self signed */
        !          2232:                issuer = subject;
        !          2233:                if (!cert->public_key)
        !          2234:                {
        !          2235:                        cert->public_key = sign_key->get_public_key(sign_key);
        !          2236:                }
        !          2237:                cert->flags |= X509_SELF_SIGNED;
        !          2238:        }
        !          2239:        cert->issuer = issuer->clone(issuer);
        !          2240:        if (!cert->notBefore)
        !          2241:        {
        !          2242:                cert->notBefore = time(NULL);
        !          2243:        }
        !          2244:        if (!cert->notAfter)
        !          2245:        {       /* defaults to 1 year from now */
        !          2246:                cert->notAfter = cert->notBefore + 60 * 60 * 24 * 365;
        !          2247:        }
        !          2248: 
        !          2249:        /* select signature scheme, if not already specified */
        !          2250:        if (!cert->scheme)
        !          2251:        {
        !          2252:                INIT(cert->scheme,
        !          2253:                        .scheme = signature_scheme_from_oid(
        !          2254:                                                                hasher_signature_algorithm_to_oid(digest_alg,
        !          2255:                                                                                                sign_key->get_type(sign_key))),
        !          2256:                );
        !          2257:        }
        !          2258:        if (cert->scheme->scheme == SIGN_UNKNOWN)
        !          2259:        {
        !          2260:                return FALSE;
        !          2261:        }
        !          2262:        if (!signature_params_build(cert->scheme, &sig_scheme))
        !          2263:        {
        !          2264:                return FALSE;
        !          2265:        }
        !          2266: 
        !          2267:        if (!cert->public_key->get_encoding(cert->public_key,
        !          2268:                                                                                PUBKEY_SPKI_ASN1_DER, &key_info))
        !          2269:        {
        !          2270:                chunk_free(&sig_scheme);
        !          2271:                return FALSE;
        !          2272:        }
        !          2273: 
        !          2274:        /* encode subjectAltNames */
        !          2275:        subjectAltNames = x509_build_subjectAltNames(cert->subjectAltNames);
        !          2276: 
        !          2277:        crlDistributionPoints = x509_build_crlDistributionPoints(cert->crl_uris,
        !          2278:                                                                                                OID_CRL_DISTRIBUTION_POINTS);
        !          2279: 
        !          2280:        /* encode OCSP URIs in authorityInfoAccess extension */
        !          2281:        enumerator = cert->ocsp_uris->create_enumerator(cert->ocsp_uris);
        !          2282:        while (enumerator->enumerate(enumerator, &uri))
        !          2283:        {
        !          2284:                chunk_t accessDescription;
        !          2285: 
        !          2286:                accessDescription = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2287:                                                                asn1_build_known_oid(OID_OCSP),
        !          2288:                                                                asn1_wrap(ASN1_CONTEXT_S_6, "c",
        !          2289:                                                                                  chunk_create(uri, strlen(uri))));
        !          2290:                authorityInfoAccess = chunk_cat("mm", authorityInfoAccess,
        !          2291:                                                                                accessDescription);
        !          2292:        }
        !          2293:        enumerator->destroy(enumerator);
        !          2294:        if (authorityInfoAccess.ptr)
        !          2295:        {
        !          2296:                authorityInfoAccess = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2297:                                        asn1_build_known_oid(OID_AUTHORITY_INFO_ACCESS),
        !          2298:                                        asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2299:                                                asn1_wrap(ASN1_SEQUENCE, "m", authorityInfoAccess)));
        !          2300:        }
        !          2301: 
        !          2302:        /* build CA basicConstraint and keyUsage flags for CA certificates */
        !          2303:        if (cert->flags & X509_CA)
        !          2304:        {
        !          2305:                chunk_t pathLenConstraint = chunk_empty;
        !          2306: 
        !          2307:                if (cert->pathLenConstraint != X509_NO_CONSTRAINT)
        !          2308:                {
        !          2309:                        pathLenConstraint = asn1_integer("c",
        !          2310:                                                                        chunk_from_thing(cert->pathLenConstraint));
        !          2311:                }
        !          2312:                basicConstraints = asn1_wrap(ASN1_SEQUENCE, "mmm",
        !          2313:                                                                asn1_build_known_oid(OID_BASIC_CONSTRAINTS),
        !          2314:                                                                asn1_wrap(ASN1_BOOLEAN, "c",
        !          2315:                                                                        chunk_from_chars(0xFF)),
        !          2316:                                                                asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2317:                                                                                asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2318:                                                                                        asn1_wrap(ASN1_BOOLEAN, "c",
        !          2319:                                                                                                chunk_from_chars(0xFF)),
        !          2320:                                                                                        pathLenConstraint)));
        !          2321:                /* set CertificateSign and implicitly CRLsign */
        !          2322:                keyUsageBits = keyUsageCertSignCrlSign;
        !          2323:        }
        !          2324:        else if (cert->flags & X509_CRL_SIGN)
        !          2325:        {
        !          2326:                keyUsageBits = keyUsageCrlSign;
        !          2327:        }
        !          2328:        if (keyUsageBits.len)
        !          2329:        {
        !          2330:                keyUsage = asn1_wrap(ASN1_SEQUENCE, "mmm",
        !          2331:                                                asn1_build_known_oid(OID_KEY_USAGE),
        !          2332:                                                asn1_wrap(ASN1_BOOLEAN, "c", chunk_from_chars(0xFF)),
        !          2333:                                                asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2334:                                                        asn1_wrap(ASN1_BIT_STRING, "c", keyUsageBits)));
        !          2335:        }
        !          2336: 
        !          2337:        /* add extendedKeyUsage flags */
        !          2338:        if (cert->flags & X509_SERVER_AUTH)
        !          2339:        {
        !          2340:                serverAuth = asn1_build_known_oid(OID_SERVER_AUTH);
        !          2341:        }
        !          2342:        if (cert->flags & X509_CLIENT_AUTH)
        !          2343:        {
        !          2344:                clientAuth = asn1_build_known_oid(OID_CLIENT_AUTH);
        !          2345:        }
        !          2346:        if (cert->flags & X509_IKE_INTERMEDIATE)
        !          2347:        {
        !          2348:                ikeIntermediate = asn1_build_known_oid(OID_IKE_INTERMEDIATE);
        !          2349:        }
        !          2350:        if (cert->flags & X509_OCSP_SIGNER)
        !          2351:        {
        !          2352:                ocspSigning = asn1_build_known_oid(OID_OCSP_SIGNING);
        !          2353:        }
        !          2354:        if (cert->flags & X509_MS_SMARTCARD_LOGON)
        !          2355:        {
        !          2356:                msSmartcardLogon = asn1_build_known_oid(OID_MS_SMARTCARD_LOGON);
        !          2357:        }
        !          2358: 
        !          2359:        if (serverAuth.ptr  || clientAuth.ptr || ikeIntermediate.ptr ||
        !          2360:                ocspSigning.ptr || msSmartcardLogon.ptr)
        !          2361:        {
        !          2362:                extendedKeyUsage = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2363:                                                                asn1_build_known_oid(OID_EXTENDED_KEY_USAGE),
        !          2364:                                                                asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2365:                                                                        asn1_wrap(ASN1_SEQUENCE, "mmmmm",
        !          2366:                                                                                serverAuth, clientAuth, ikeIntermediate,
        !          2367:                                                                                ocspSigning, msSmartcardLogon)));
        !          2368:        }
        !          2369: 
        !          2370:        /* add subjectKeyIdentifier to CA and OCSP signer certificates */
        !          2371:        if (cert->flags & (X509_CA | X509_OCSP_SIGNER | X509_CRL_SIGN))
        !          2372:        {
        !          2373:                chunk_t keyid;
        !          2374: 
        !          2375:                if (cert->public_key->get_fingerprint(cert->public_key,
        !          2376:                                                                                          KEYID_PUBKEY_SHA1, &keyid))
        !          2377:                {
        !          2378:                        subjectKeyIdentifier = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2379:                                                                        asn1_build_known_oid(OID_SUBJECT_KEY_ID),
        !          2380:                                                                        asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2381:                                                                                asn1_wrap(ASN1_OCTET_STRING, "c", keyid)));
        !          2382:                }
        !          2383:        }
        !          2384: 
        !          2385:        /* add the keyid authKeyIdentifier for non self-signed certificates */
        !          2386:        if (sign_cert)
        !          2387:        {
        !          2388:                chunk_t keyid;
        !          2389: 
        !          2390:                if (sign_key->get_fingerprint(sign_key, KEYID_PUBKEY_SHA1, &keyid))
        !          2391:                {
        !          2392:                        authKeyIdentifier = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2393:                                                        asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
        !          2394:                                                        asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2395:                                                                asn1_wrap(ASN1_SEQUENCE, "m",
        !          2396:                                                                        asn1_wrap(ASN1_CONTEXT_S_0, "c", keyid))));
        !          2397:                }
        !          2398:        }
        !          2399: 
        !          2400:        if (cert->ipAddrBlocks->get_count(cert->ipAddrBlocks))
        !          2401:        {
        !          2402:                chunk_t v4blocks = chunk_empty, v6blocks = chunk_empty, block;
        !          2403:                traffic_selector_t *ts;
        !          2404: 
        !          2405:                enumerator = cert->ipAddrBlocks->create_enumerator(cert->ipAddrBlocks);
        !          2406:                while (enumerator->enumerate(enumerator, &ts))
        !          2407:                {
        !          2408:                        switch (ts->get_type(ts))
        !          2409:                        {
        !          2410:                                case TS_IPV4_ADDR_RANGE:
        !          2411:                                        block = generate_ts(ts);
        !          2412:                                        v4blocks = chunk_cat("mm", v4blocks, block);
        !          2413:                                        break;
        !          2414:                                case TS_IPV6_ADDR_RANGE:
        !          2415:                                        block = generate_ts(ts);
        !          2416:                                        v6blocks = chunk_cat("mm", v6blocks, block);
        !          2417:                                        break;
        !          2418:                                default:
        !          2419:                                        break;
        !          2420:                        }
        !          2421:                }
        !          2422:                enumerator->destroy(enumerator);
        !          2423: 
        !          2424:                if (v4blocks.ptr)
        !          2425:                {
        !          2426:                        v4blocks = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2427:                                                asn1_wrap(ASN1_OCTET_STRING, "c",
        !          2428:                                                        chunk_from_chars(0x00,0x01)),
        !          2429:                                                asn1_wrap(ASN1_SEQUENCE, "m", v4blocks));
        !          2430:                }
        !          2431:                if (v6blocks.ptr)
        !          2432:                {
        !          2433:                        v6blocks = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2434:                                                asn1_wrap(ASN1_OCTET_STRING, "c",
        !          2435:                                                        chunk_from_chars(0x00,0x02)),
        !          2436:                                                asn1_wrap(ASN1_SEQUENCE, "m", v6blocks));
        !          2437:                }
        !          2438:                ipAddrBlocks = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2439:                                                asn1_build_known_oid(OID_IP_ADDR_BLOCKS),
        !          2440:                                                asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2441:                                                        asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2442:                                                                v4blocks, v6blocks)));
        !          2443:                cert->flags |= X509_IP_ADDR_BLOCKS;
        !          2444:        }
        !          2445: 
        !          2446:        if (cert->permitted_names->get_count(cert->permitted_names) ||
        !          2447:                cert->excluded_names->get_count(cert->excluded_names))
        !          2448:        {
        !          2449:                chunk_t permitted = chunk_empty, excluded = chunk_empty, subtree;
        !          2450:                identification_t *id;
        !          2451: 
        !          2452:                enumerator = create_name_constraint_enumerator(cert, TRUE);
        !          2453:                while (enumerator->enumerate(enumerator, &id))
        !          2454:                {
        !          2455:                        subtree = asn1_wrap(ASN1_SEQUENCE, "m", build_generalName(id));
        !          2456:                        permitted = chunk_cat("mm", permitted, subtree);
        !          2457:                }
        !          2458:                enumerator->destroy(enumerator);
        !          2459:                if (permitted.ptr)
        !          2460:                {
        !          2461:                        permitted = asn1_wrap(ASN1_CONTEXT_C_0, "m", permitted);
        !          2462:                }
        !          2463: 
        !          2464:                enumerator = create_name_constraint_enumerator(cert, FALSE);
        !          2465:                while (enumerator->enumerate(enumerator, &id))
        !          2466:                {
        !          2467:                        subtree = asn1_wrap(ASN1_SEQUENCE, "m", build_generalName(id));
        !          2468:                        excluded = chunk_cat("mm", excluded, subtree);
        !          2469:                }
        !          2470:                enumerator->destroy(enumerator);
        !          2471:                if (excluded.ptr)
        !          2472:                {
        !          2473:                        excluded = asn1_wrap(ASN1_CONTEXT_C_1, "m", excluded);
        !          2474:                }
        !          2475: 
        !          2476:                nameConstraints = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2477:                                                        asn1_build_known_oid(OID_NAME_CONSTRAINTS),
        !          2478:                                                        asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2479:                                                                asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2480:                                                                        permitted, excluded)));
        !          2481:        }
        !          2482: 
        !          2483:        if (cert->cert_policies->get_count(cert->cert_policies))
        !          2484:        {
        !          2485:                x509_cert_policy_t *policy;
        !          2486: 
        !          2487:                enumerator = create_cert_policy_enumerator(cert);
        !          2488:                while (enumerator->enumerate(enumerator, &policy))
        !          2489:                {
        !          2490:                        chunk_t chunk = chunk_empty, cps = chunk_empty, notice = chunk_empty;
        !          2491: 
        !          2492:                        if (policy->cps_uri)
        !          2493:                        {
        !          2494:                                cps = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2495:                                                asn1_build_known_oid(OID_POLICY_QUALIFIER_CPS),
        !          2496:                                                asn1_wrap(ASN1_IA5STRING, "c",
        !          2497:                                                        chunk_create(policy->cps_uri,
        !          2498:                                                                                 strlen(policy->cps_uri))));
        !          2499:                        }
        !          2500:                        if (policy->unotice_text)
        !          2501:                        {
        !          2502:                                notice = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2503:                                                        asn1_build_known_oid(OID_POLICY_QUALIFIER_UNOTICE),
        !          2504:                                                        asn1_wrap(ASN1_SEQUENCE, "m",
        !          2505:                                                                asn1_wrap(ASN1_VISIBLESTRING, "c",
        !          2506:                                                                        chunk_create(policy->unotice_text,
        !          2507:                                                                                strlen(policy->unotice_text)))));
        !          2508:                        }
        !          2509:                        if (cps.len || notice.len)
        !          2510:                        {
        !          2511:                                chunk = asn1_wrap(ASN1_SEQUENCE, "mm", cps, notice);
        !          2512:                        }
        !          2513:                        chunk = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2514:                                                asn1_wrap(ASN1_OID, "c", policy->oid), chunk);
        !          2515:                        certPolicies = chunk_cat("mm", certPolicies, chunk);
        !          2516:                }
        !          2517:                enumerator->destroy(enumerator);
        !          2518: 
        !          2519:                certPolicies = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2520:                                                        asn1_build_known_oid(OID_CERTIFICATE_POLICIES),
        !          2521:                                                        asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2522:                                                                asn1_wrap(ASN1_SEQUENCE, "m", certPolicies)));
        !          2523:        }
        !          2524: 
        !          2525:        if (cert->policy_mappings->get_count(cert->policy_mappings))
        !          2526:        {
        !          2527:                x509_policy_mapping_t *mapping;
        !          2528: 
        !          2529:                enumerator = create_policy_mapping_enumerator(cert);
        !          2530:                while (enumerator->enumerate(enumerator, &mapping))
        !          2531:                {
        !          2532:                        chunk_t chunk;
        !          2533: 
        !          2534:                        chunk = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2535:                                                asn1_wrap(ASN1_OID, "c", mapping->issuer),
        !          2536:                                                asn1_wrap(ASN1_OID, "c", mapping->subject));
        !          2537:                        policyMappings = chunk_cat("mm", policyMappings, chunk);
        !          2538:                }
        !          2539:                enumerator->destroy(enumerator);
        !          2540: 
        !          2541:                policyMappings = asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2542:                                                        asn1_build_known_oid(OID_POLICY_MAPPINGS),
        !          2543:                                                        asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2544:                                                                asn1_wrap(ASN1_SEQUENCE, "m", policyMappings)));
        !          2545:        }
        !          2546: 
        !          2547:        if (cert->inhibit_mapping != X509_NO_CONSTRAINT ||
        !          2548:                cert->require_explicit != X509_NO_CONSTRAINT)
        !          2549:        {
        !          2550:                chunk_t inhibit = chunk_empty, explicit = chunk_empty;
        !          2551: 
        !          2552:                if (cert->require_explicit != X509_NO_CONSTRAINT)
        !          2553:                {
        !          2554:                        explicit = asn1_wrap(ASN1_CONTEXT_C_0, "m",
        !          2555:                                                asn1_integer("c",
        !          2556:                                                        chunk_from_thing(cert->require_explicit)));
        !          2557:                }
        !          2558:                if (cert->inhibit_mapping != X509_NO_CONSTRAINT)
        !          2559:                {
        !          2560:                        inhibit = asn1_wrap(ASN1_CONTEXT_C_1, "m",
        !          2561:                                                asn1_integer("c",
        !          2562:                                                        chunk_from_thing(cert->inhibit_mapping)));
        !          2563:                }
        !          2564:                policyConstraints = asn1_wrap(ASN1_SEQUENCE, "mmm",
        !          2565:                                                asn1_build_known_oid(OID_POLICY_CONSTRAINTS),
        !          2566:                                                asn1_wrap(ASN1_BOOLEAN, "c", chunk_from_chars(0xFF)),
        !          2567:                                                asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2568:                                                        asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2569:                                                                explicit, inhibit)));
        !          2570:        }
        !          2571: 
        !          2572:        if (cert->inhibit_any != X509_NO_CONSTRAINT)
        !          2573:        {
        !          2574:                inhibitAnyPolicy = asn1_wrap(ASN1_SEQUENCE, "mmm",
        !          2575:                                asn1_build_known_oid(OID_INHIBIT_ANY_POLICY),
        !          2576:                                asn1_wrap(ASN1_BOOLEAN, "c", chunk_from_chars(0xFF)),
        !          2577:                                asn1_wrap(ASN1_OCTET_STRING, "m",
        !          2578:                                        asn1_integer("c",
        !          2579:                                                chunk_from_thing(cert->inhibit_any))));
        !          2580:        }
        !          2581: 
        !          2582:        if (cert->critical_extension_oid.len > 0)
        !          2583:        {
        !          2584:                criticalExtension = asn1_wrap(ASN1_SEQUENCE, "mmm",
        !          2585:                                        asn1_simple_object(ASN1_OID, cert->critical_extension_oid),
        !          2586:                                        asn1_simple_object(ASN1_BOOLEAN, chunk_from_chars(0xFF)),
        !          2587:                                        asn1_simple_object(ASN1_OCTET_STRING, chunk_empty));
        !          2588:        }
        !          2589: 
        !          2590:        if (basicConstraints.ptr || subjectAltNames.ptr || authKeyIdentifier.ptr ||
        !          2591:                crlDistributionPoints.ptr || nameConstraints.ptr || ipAddrBlocks.ptr)
        !          2592:        {
        !          2593:                extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m",
        !          2594:                                                asn1_wrap(ASN1_SEQUENCE, "mmmmmmmmmmmmmmm",
        !          2595:                                                        basicConstraints, keyUsage, subjectKeyIdentifier,
        !          2596:                                                        authKeyIdentifier, subjectAltNames,
        !          2597:                                                        extendedKeyUsage, crlDistributionPoints,
        !          2598:                                                        authorityInfoAccess, nameConstraints, certPolicies,
        !          2599:                                                        policyMappings, policyConstraints, inhibitAnyPolicy,
        !          2600:                                                        ipAddrBlocks, criticalExtension));
        !          2601:        }
        !          2602: 
        !          2603:        cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmccmcmm",
        !          2604:                asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2),
        !          2605:                asn1_integer("c", cert->serialNumber),
        !          2606:                sig_scheme,
        !          2607:                issuer->get_encoding(issuer),
        !          2608:                asn1_wrap(ASN1_SEQUENCE, "mm",
        !          2609:                        asn1_from_time(&cert->notBefore, ASN1_UTCTIME),
        !          2610:                        asn1_from_time(&cert->notAfter, ASN1_UTCTIME)),
        !          2611:                subject->get_encoding(subject),
        !          2612:                key_info, extensions);
        !          2613: 
        !          2614:        if (!sign_key->sign(sign_key, cert->scheme->scheme, cert->scheme->params,
        !          2615:                                                cert->tbsCertificate, &cert->signature))
        !          2616:        {
        !          2617:                chunk_free(&sig_scheme);
        !          2618:                return FALSE;
        !          2619:        }
        !          2620:        cert->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm", cert->tbsCertificate,
        !          2621:                                                           sig_scheme,
        !          2622:                                                           asn1_bitstring("c", cert->signature));
        !          2623: 
        !          2624:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
        !          2625:        if (!hasher ||
        !          2626:                !hasher->allocate_hash(hasher, cert->encoding, &cert->encoding_hash))
        !          2627:        {
        !          2628:                DESTROY_IF(hasher);
        !          2629:                return FALSE;
        !          2630:        }
        !          2631:        hasher->destroy(hasher);
        !          2632:        return TRUE;
        !          2633: }
        !          2634: 
        !          2635: /**
        !          2636:  * See header.
        !          2637:  */
        !          2638: x509_cert_t *x509_cert_load(certificate_type_t type, va_list args)
        !          2639: {
        !          2640:        x509_flag_t flags = 0;
        !          2641:        chunk_t blob = chunk_empty;
        !          2642: 
        !          2643:        while (TRUE)
        !          2644:        {
        !          2645:                switch (va_arg(args, builder_part_t))
        !          2646:                {
        !          2647:                        case BUILD_BLOB_ASN1_DER:
        !          2648:                                blob = va_arg(args, chunk_t);
        !          2649:                                continue;
        !          2650:                        case BUILD_X509_FLAG:
        !          2651:                                flags |= va_arg(args, x509_flag_t);
        !          2652:                                continue;
        !          2653:                        case BUILD_END:
        !          2654:                                break;
        !          2655:                        default:
        !          2656:                                return NULL;
        !          2657:                }
        !          2658:                break;
        !          2659:        }
        !          2660: 
        !          2661:        if (blob.ptr)
        !          2662:        {
        !          2663:                private_x509_cert_t *cert = create_empty();
        !          2664: 
        !          2665:                cert->encoding = chunk_clone(blob);
        !          2666:                cert->parsed = TRUE;
        !          2667:                if (parse_certificate(cert))
        !          2668:                {
        !          2669:                        cert->flags |= flags;
        !          2670:                        return &cert->public;
        !          2671:                }
        !          2672:                destroy(cert);
        !          2673:        }
        !          2674:        return NULL;
        !          2675: }
        !          2676: 
        !          2677: /**
        !          2678:  * See header.
        !          2679:  */
        !          2680: x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args)
        !          2681: {
        !          2682:        private_x509_cert_t *cert;
        !          2683:        certificate_t *sign_cert = NULL;
        !          2684:        private_key_t *sign_key = NULL;
        !          2685:        hash_algorithm_t digest_alg = HASH_SHA256;
        !          2686:        u_int constraint;
        !          2687: 
        !          2688:        cert = create_empty();
        !          2689:        while (TRUE)
        !          2690:        {
        !          2691:                switch (va_arg(args, builder_part_t))
        !          2692:                {
        !          2693:                        case BUILD_X509_FLAG:
        !          2694:                                cert->flags |= va_arg(args, x509_flag_t);
        !          2695:                                continue;
        !          2696:                        case BUILD_SIGNING_KEY:
        !          2697:                                sign_key = va_arg(args, private_key_t*);
        !          2698:                                continue;
        !          2699:                        case BUILD_SIGNING_CERT:
        !          2700:                                sign_cert = va_arg(args, certificate_t*);
        !          2701:                                continue;
        !          2702:                        case BUILD_PUBLIC_KEY:
        !          2703:                                cert->public_key = va_arg(args, public_key_t*);
        !          2704:                                cert->public_key->get_ref(cert->public_key);
        !          2705:                                continue;
        !          2706:                        case BUILD_SUBJECT:
        !          2707:                                cert->subject = va_arg(args, identification_t*);
        !          2708:                                cert->subject = cert->subject->clone(cert->subject);
        !          2709:                                continue;
        !          2710:                        case BUILD_SUBJECT_ALTNAMES:
        !          2711:                        {
        !          2712:                                enumerator_t *enumerator;
        !          2713:                                identification_t *id;
        !          2714:                                linked_list_t *list;
        !          2715: 
        !          2716:                                list = va_arg(args, linked_list_t*);
        !          2717:                                enumerator = list->create_enumerator(list);
        !          2718:                                while (enumerator->enumerate(enumerator, &id))
        !          2719:                                {
        !          2720:                                        cert->subjectAltNames->insert_last(cert->subjectAltNames,
        !          2721:                                                                                                        id->clone(id));
        !          2722:                                }
        !          2723:                                enumerator->destroy(enumerator);
        !          2724:                                continue;
        !          2725:                        }
        !          2726:                        case BUILD_CRL_DISTRIBUTION_POINTS:
        !          2727:                        {
        !          2728:                                enumerator_t *enumerator;
        !          2729:                                linked_list_t *list;
        !          2730:                                x509_cdp_t *in, *cdp;
        !          2731: 
        !          2732:                                list = va_arg(args, linked_list_t*);
        !          2733:                                enumerator = list->create_enumerator(list);
        !          2734:                                while (enumerator->enumerate(enumerator, &in))
        !          2735:                                {
        !          2736:                                        INIT(cdp,
        !          2737:                                                .uri = strdup(in->uri),
        !          2738:                                                .issuer = in->issuer ? in->issuer->clone(in->issuer) : NULL,
        !          2739:                                        );
        !          2740:                                        cert->crl_uris->insert_last(cert->crl_uris, cdp);
        !          2741:                                }
        !          2742:                                enumerator->destroy(enumerator);
        !          2743:                                continue;
        !          2744:                        }
        !          2745:                        case BUILD_OCSP_ACCESS_LOCATIONS:
        !          2746:                        {
        !          2747:                                enumerator_t *enumerator;
        !          2748:                                linked_list_t *list;
        !          2749:                                char *uri;
        !          2750: 
        !          2751:                                list = va_arg(args, linked_list_t*);
        !          2752:                                enumerator = list->create_enumerator(list);
        !          2753:                                while (enumerator->enumerate(enumerator, &uri))
        !          2754:                                {
        !          2755:                                        cert->ocsp_uris->insert_last(cert->ocsp_uris, strdup(uri));
        !          2756:                                }
        !          2757:                                enumerator->destroy(enumerator);
        !          2758:                                continue;
        !          2759:                        }
        !          2760:                        case BUILD_PATHLEN:
        !          2761:                                constraint = va_arg(args, u_int);
        !          2762:                                cert->pathLenConstraint = (constraint < 128) ?
        !          2763:                                                                                   constraint : X509_NO_CONSTRAINT;
        !          2764:                                continue;
        !          2765:                        case BUILD_ADDRBLOCKS:
        !          2766:                        {
        !          2767:                                enumerator_t *enumerator;
        !          2768:                                traffic_selector_t *ts;
        !          2769:                                linked_list_t *list;
        !          2770: 
        !          2771:                                list = va_arg(args, linked_list_t*);
        !          2772:                                enumerator = list->create_enumerator(list);
        !          2773:                                while (enumerator->enumerate(enumerator, &ts))
        !          2774:                                {
        !          2775:                                        cert->ipAddrBlocks->insert_last(cert->ipAddrBlocks,
        !          2776:                                                                                                        ts->clone(ts));
        !          2777:                                }
        !          2778:                                enumerator->destroy(enumerator);
        !          2779:                                continue;
        !          2780:                        }
        !          2781:                        case BUILD_PERMITTED_NAME_CONSTRAINTS:
        !          2782:                        {
        !          2783:                                enumerator_t *enumerator;
        !          2784:                                linked_list_t *list;
        !          2785:                                identification_t *constraint;
        !          2786: 
        !          2787:                                list = va_arg(args, linked_list_t*);
        !          2788:                                enumerator = list->create_enumerator(list);
        !          2789:                                while (enumerator->enumerate(enumerator, &constraint))
        !          2790:                                {
        !          2791:                                        cert->permitted_names->insert_last(cert->permitted_names,
        !          2792:                                                                                                constraint->clone(constraint));
        !          2793:                                }
        !          2794:                                enumerator->destroy(enumerator);
        !          2795:                                continue;
        !          2796:                        }
        !          2797:                        case BUILD_EXCLUDED_NAME_CONSTRAINTS:
        !          2798:                        {
        !          2799:                                enumerator_t *enumerator;
        !          2800:                                linked_list_t *list;
        !          2801:                                identification_t *constraint;
        !          2802: 
        !          2803:                                list = va_arg(args, linked_list_t*);
        !          2804:                                enumerator = list->create_enumerator(list);
        !          2805:                                while (enumerator->enumerate(enumerator, &constraint))
        !          2806:                                {
        !          2807:                                        cert->excluded_names->insert_last(cert->excluded_names,
        !          2808:                                                                                                constraint->clone(constraint));
        !          2809:                                }
        !          2810:                                enumerator->destroy(enumerator);
        !          2811:                                continue;
        !          2812:                        }
        !          2813:                        case BUILD_CERTIFICATE_POLICIES:
        !          2814:                        {
        !          2815:                                enumerator_t *enumerator;
        !          2816:                                linked_list_t *list;
        !          2817:                                x509_cert_policy_t *policy, *in;
        !          2818: 
        !          2819:                                list = va_arg(args, linked_list_t*);
        !          2820:                                enumerator = list->create_enumerator(list);
        !          2821:                                while (enumerator->enumerate(enumerator, &in))
        !          2822:                                {
        !          2823:                                        INIT(policy,
        !          2824:                                                .oid = chunk_clone(in->oid),
        !          2825:                                                .cps_uri = strdupnull(in->cps_uri),
        !          2826:                                                .unotice_text = strdupnull(in->unotice_text),
        !          2827:                                        );
        !          2828:                                        cert->cert_policies->insert_last(cert->cert_policies, policy);
        !          2829:                                }
        !          2830:                                enumerator->destroy(enumerator);
        !          2831:                                continue;
        !          2832:                        }
        !          2833:                        case BUILD_POLICY_MAPPINGS:
        !          2834:                        {
        !          2835:                                enumerator_t *enumerator;
        !          2836:                                linked_list_t *list;
        !          2837:                                x509_policy_mapping_t* mapping, *in;
        !          2838: 
        !          2839:                                list = va_arg(args, linked_list_t*);
        !          2840:                                enumerator = list->create_enumerator(list);
        !          2841:                                while (enumerator->enumerate(enumerator, &in))
        !          2842:                                {
        !          2843:                                        INIT(mapping,
        !          2844:                                                .issuer = chunk_clone(in->issuer),
        !          2845:                                                .subject = chunk_clone(in->subject),
        !          2846:                                        );
        !          2847:                                        cert->policy_mappings->insert_last(cert->policy_mappings,
        !          2848:                                                                                                           mapping);
        !          2849:                                }
        !          2850:                                enumerator->destroy(enumerator);
        !          2851:                                continue;
        !          2852:                        }
        !          2853:                        case BUILD_POLICY_REQUIRE_EXPLICIT:
        !          2854:                                constraint = va_arg(args, u_int);
        !          2855:                                cert->require_explicit = (constraint < 128) ?
        !          2856:                                                                                  constraint : X509_NO_CONSTRAINT;
        !          2857:                                continue;
        !          2858:                        case BUILD_POLICY_INHIBIT_MAPPING:
        !          2859:                                constraint = va_arg(args, u_int);
        !          2860:                                cert->inhibit_mapping = (constraint < 128) ?
        !          2861:                                                                                 constraint : X509_NO_CONSTRAINT;
        !          2862:                                continue;
        !          2863:                        case BUILD_POLICY_INHIBIT_ANY:
        !          2864:                                constraint = va_arg(args, u_int);
        !          2865:                                cert->inhibit_any = (constraint < 128) ?
        !          2866:                                                                         constraint : X509_NO_CONSTRAINT;
        !          2867:                                continue;
        !          2868:                        case BUILD_NOT_BEFORE_TIME:
        !          2869:                                cert->notBefore = va_arg(args, time_t);
        !          2870:                                continue;
        !          2871:                        case BUILD_NOT_AFTER_TIME:
        !          2872:                                cert->notAfter = va_arg(args, time_t);
        !          2873:                                continue;
        !          2874:                        case BUILD_SERIAL:
        !          2875:                                cert->serialNumber = chunk_clone(va_arg(args, chunk_t));
        !          2876:                                continue;
        !          2877:                        case BUILD_SIGNATURE_SCHEME:
        !          2878:                                cert->scheme = va_arg(args, signature_params_t*);
        !          2879:                                cert->scheme = signature_params_clone(cert->scheme);
        !          2880:                                continue;
        !          2881:                        case BUILD_DIGEST_ALG:
        !          2882:                                digest_alg = va_arg(args, int);
        !          2883:                                continue;
        !          2884:                        case BUILD_CRITICAL_EXTENSION:
        !          2885:                                cert->critical_extension_oid = chunk_clone(va_arg(args, chunk_t));
        !          2886:                                continue;
        !          2887:                        case BUILD_END:
        !          2888:                                break;
        !          2889:                        default:
        !          2890:                                destroy(cert);
        !          2891:                                return NULL;
        !          2892:                }
        !          2893:                break;
        !          2894:        }
        !          2895: 
        !          2896:        if (sign_key && generate(cert, sign_cert, sign_key, digest_alg))
        !          2897:        {
        !          2898:                return &cert->public;
        !          2899:        }
        !          2900:        destroy(cert);
        !          2901:        return NULL;
        !          2902: }

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