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

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2014-2017 Tobias Brunner
        !             3:  * Copyright (C) 2008-2009 Martin Willi
        !             4:  * Copyright (C) 2017 Andreas Steffen
        !             5:  * HSR Hochschule fuer Technik Rapperswil
        !             6:  *
        !             7:  * This program is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2 of the License, or (at your
        !            10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            11:  *
        !            12:  * This program is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            15:  * for more details.
        !            16:  */
        !            17: 
        !            18: #include "x509_crl.h"
        !            19: 
        !            20: typedef struct private_x509_crl_t private_x509_crl_t;
        !            21: typedef struct revoked_t revoked_t;
        !            22: 
        !            23: #include <time.h>
        !            24: 
        !            25: #include <utils/debug.h>
        !            26: #include <library.h>
        !            27: #include <asn1/oid.h>
        !            28: #include <asn1/asn1.h>
        !            29: #include <asn1/asn1_parser.h>
        !            30: #include <credentials/certificates/x509.h>
        !            31: #include <credentials/keys/private_key.h>
        !            32: #include <collections/linked_list.h>
        !            33: 
        !            34: /**
        !            35:  * entry for a revoked certificate
        !            36:  */
        !            37: struct revoked_t {
        !            38:        /**
        !            39:         * serial of the revoked certificate
        !            40:         */
        !            41:        chunk_t serial;
        !            42: 
        !            43:        /**
        !            44:         * date of revocation
        !            45:         */
        !            46:        time_t date;
        !            47: 
        !            48:        /**
        !            49:         * reason for revocation
        !            50:         */
        !            51:        crl_reason_t reason;
        !            52: };
        !            53: 
        !            54: /**
        !            55:  * private data of x509_crl
        !            56:  */
        !            57: struct private_x509_crl_t {
        !            58: 
        !            59:        /**
        !            60:         * public functions
        !            61:         */
        !            62:        x509_crl_t public;
        !            63: 
        !            64:        /**
        !            65:         * X.509 crl encoding in ASN.1 DER format
        !            66:         */
        !            67:        chunk_t encoding;
        !            68: 
        !            69:        /**
        !            70:         * X.509 crl body over which signature is computed
        !            71:         */
        !            72:        chunk_t tbsCertList;
        !            73: 
        !            74:        /**
        !            75:         * Version of the X.509 crl
        !            76:         */
        !            77:        u_int version;
        !            78: 
        !            79:        /**
        !            80:         * ID representing the crl issuer
        !            81:         */
        !            82:        identification_t *issuer;
        !            83: 
        !            84:        /**
        !            85:         * CRL number
        !            86:         */
        !            87:        chunk_t crlNumber;
        !            88: 
        !            89:        /**
        !            90:         * Time when the crl was generated
        !            91:         */
        !            92:        time_t thisUpdate;
        !            93: 
        !            94:        /**
        !            95:         * Time when an update crl will be available
        !            96:         */
        !            97:        time_t nextUpdate;
        !            98: 
        !            99:        /**
        !           100:         * list of revoked certificates as revoked_t
        !           101:         */
        !           102:        linked_list_t *revoked;
        !           103: 
        !           104:        /**
        !           105:         * List of Freshest CRL distribution points
        !           106:         */
        !           107:        linked_list_t *crl_uris;
        !           108: 
        !           109:        /**
        !           110:         * Authority Key Identifier
        !           111:         */
        !           112:        chunk_t authKeyIdentifier;
        !           113: 
        !           114:        /**
        !           115:         * Authority Key Serial Number
        !           116:         */
        !           117:        chunk_t authKeySerialNumber;
        !           118: 
        !           119:        /**
        !           120:         * Optional OID of an [unsupported] critical extension
        !           121:         */
        !           122:        chunk_t critical_extension_oid;
        !           123: 
        !           124:        /**
        !           125:         * Number of BaseCRL, if a delta CRL
        !           126:         */
        !           127:        chunk_t baseCrlNumber;
        !           128: 
        !           129:        /**
        !           130:         * Signature scheme
        !           131:         */
        !           132:        signature_params_t *scheme;
        !           133: 
        !           134:        /**
        !           135:         * Signature
        !           136:         */
        !           137:        chunk_t signature;
        !           138: 
        !           139:        /**
        !           140:         * has this CRL been generated
        !           141:         */
        !           142:        bool generated;
        !           143: 
        !           144:        /**
        !           145:         * reference counter
        !           146:         */
        !           147:        refcount_t ref;
        !           148: };
        !           149: 
        !           150: /**
        !           151:  * from x509_cert
        !           152:  */
        !           153: extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob, int level0,
        !           154:                                                                                                 chunk_t *authKeySerialNumber);
        !           155: 
        !           156: /**
        !           157:  * from x509_cert
        !           158:  */
        !           159: extern bool x509_parse_crlDistributionPoints(chunk_t blob, int level0,
        !           160:                                                                                         linked_list_t *list);
        !           161: 
        !           162: /**
        !           163:  * from x509_cert
        !           164:  */
        !           165: extern chunk_t x509_build_crlDistributionPoints(linked_list_t *list, int extn);
        !           166: 
        !           167: /**
        !           168:   * ASN.1 definition of an X.509 certificate revocation list
        !           169:  */
        !           170: static const asn1Object_t crlObjects[] = {
        !           171:        { 0, "certificateList",                         ASN1_SEQUENCE,     ASN1_OBJ  }, /*  0 */
        !           172:        { 1,   "tbsCertList",                           ASN1_SEQUENCE,     ASN1_OBJ  }, /*  1 */
        !           173:        { 2,     "version",                                     ASN1_INTEGER,      ASN1_OPT |
        !           174:                                                                                                                   ASN1_BODY }, /*  2 */
        !           175:        { 2,     "end opt",                                     ASN1_EOC,          ASN1_END  }, /*  3 */
        !           176:        { 2,     "signature",                           ASN1_EOC,          ASN1_RAW  }, /*  4 */
        !           177:        { 2,     "issuer",                                      ASN1_SEQUENCE,     ASN1_OBJ  }, /*  5 */
        !           178:        { 2,     "thisUpdate",                          ASN1_EOC,          ASN1_RAW  }, /*  6 */
        !           179:        { 2,     "nextUpdate",                          ASN1_EOC,          ASN1_RAW  }, /*  7 */
        !           180:        { 2,     "revokedCertificates",         ASN1_SEQUENCE,     ASN1_OPT |
        !           181:                                                                                                                   ASN1_LOOP }, /*  8 */
        !           182:        { 3,       "certList",                          ASN1_SEQUENCE,     ASN1_NONE }, /*  9 */
        !           183:        { 4,         "userCertificate",         ASN1_INTEGER,      ASN1_BODY }, /* 10 */
        !           184:        { 4,         "revocationDate",          ASN1_EOC,          ASN1_RAW  }, /* 11 */
        !           185:        { 4,         "crlEntryExtensions",  ASN1_SEQUENCE,     ASN1_OPT |
        !           186:                                                                                                                   ASN1_LOOP }, /* 12 */
        !           187:        { 5,           "extension",                     ASN1_SEQUENCE,     ASN1_NONE }, /* 13 */
        !           188:        { 6,             "extnID",                      ASN1_OID,          ASN1_BODY }, /* 14 */
        !           189:        { 6,             "critical",            ASN1_BOOLEAN,      ASN1_DEF |
        !           190:                                                                                                                   ASN1_BODY }, /* 15 */
        !           191:        { 6,             "extnValue",           ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */
        !           192:        { 4,         "end opt or loop",         ASN1_EOC,          ASN1_END  }, /* 17 */
        !           193:        { 2,     "end opt or loop",                     ASN1_EOC,          ASN1_END  }, /* 18 */
        !           194:        { 2,     "optional extensions",         ASN1_CONTEXT_C_0,  ASN1_OPT  }, /* 19 */
        !           195:        { 3,       "crlExtensions",                     ASN1_SEQUENCE,     ASN1_LOOP }, /* 20 */
        !           196:        { 4,         "extension",                       ASN1_SEQUENCE,     ASN1_NONE }, /* 21 */
        !           197:        { 5,           "extnID",                        ASN1_OID,          ASN1_BODY }, /* 22 */
        !           198:        { 5,           "critical",                      ASN1_BOOLEAN,      ASN1_DEF |
        !           199:                                                                                                                   ASN1_BODY }, /* 23 */
        !           200:        { 5,           "extnValue",                     ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */
        !           201:        { 3,       "end loop",                          ASN1_EOC,          ASN1_END  }, /* 25 */
        !           202:        { 2,     "end opt",                                     ASN1_EOC,          ASN1_END  }, /* 26 */
        !           203:        { 1,   "signatureAlgorithm",            ASN1_EOC,          ASN1_RAW  }, /* 27 */
        !           204:        { 1,   "signatureValue",                        ASN1_BIT_STRING,   ASN1_BODY }, /* 28 */
        !           205:        { 0, "exit",                                            ASN1_EOC,                  ASN1_EXIT }
        !           206: };
        !           207: #define CRL_OBJ_TBS_CERT_LIST                   1
        !           208: #define CRL_OBJ_VERSION                                         2
        !           209: #define CRL_OBJ_SIG_ALG                                         4
        !           210: #define CRL_OBJ_ISSUER                                  5
        !           211: #define CRL_OBJ_THIS_UPDATE                             6
        !           212: #define CRL_OBJ_NEXT_UPDATE                             7
        !           213: #define CRL_OBJ_USER_CERTIFICATE               10
        !           214: #define CRL_OBJ_REVOCATION_DATE                        11
        !           215: #define CRL_OBJ_CRL_ENTRY_EXTN_ID              14
        !           216: #define CRL_OBJ_CRL_ENTRY_CRITICAL             15
        !           217: #define CRL_OBJ_CRL_ENTRY_EXTN_VALUE   16
        !           218: #define CRL_OBJ_EXTN_ID                                        22
        !           219: #define CRL_OBJ_CRITICAL                               23
        !           220: #define CRL_OBJ_EXTN_VALUE                             24
        !           221: #define CRL_OBJ_ALGORITHM                              27
        !           222: #define CRL_OBJ_SIGNATURE                              28
        !           223: 
        !           224: /**
        !           225:  *  Parses an X.509 Certificate Revocation List (CRL)
        !           226:  */
        !           227: static bool parse(private_x509_crl_t *this)
        !           228: {
        !           229:        asn1_parser_t *parser;
        !           230:        chunk_t object;
        !           231:        chunk_t extnID = chunk_empty;
        !           232:        chunk_t userCertificate = chunk_empty;
        !           233:        int objectID;
        !           234:        signature_params_t sig_alg = {};
        !           235:        bool success = FALSE;
        !           236:        bool critical = FALSE;
        !           237:        revoked_t *revoked = NULL;
        !           238: 
        !           239:        parser = asn1_parser_create(crlObjects, this->encoding);
        !           240: 
        !           241:        while (parser->iterate(parser, &objectID, &object))
        !           242:        {
        !           243:                u_int level = parser->get_level(parser)+1;
        !           244: 
        !           245:                switch (objectID)
        !           246:                {
        !           247:                        case CRL_OBJ_TBS_CERT_LIST:
        !           248:                                this->tbsCertList = object;
        !           249:                                break;
        !           250:                        case CRL_OBJ_VERSION:
        !           251:                                this->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
        !           252:                                DBG2(DBG_ASN, "  v%d", this->version);
        !           253:                                break;
        !           254:                        case CRL_OBJ_SIG_ALG:
        !           255:                                if (!signature_params_parse(object, level, &sig_alg))
        !           256:                                {
        !           257:                                        DBG1(DBG_ASN, "  unable to parse signature algorithm");
        !           258:                                        goto end;
        !           259:                                }
        !           260:                                break;
        !           261:                        case CRL_OBJ_ISSUER:
        !           262:                                this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
        !           263:                                DBG2(DBG_ASN, "  '%Y'", this->issuer);
        !           264:                                break;
        !           265:                        case CRL_OBJ_THIS_UPDATE:
        !           266:                                this->thisUpdate = asn1_parse_time(object, level);
        !           267:                                break;
        !           268:                        case CRL_OBJ_NEXT_UPDATE:
        !           269:                                this->nextUpdate = asn1_parse_time(object, level);
        !           270:                                break;
        !           271:                        case CRL_OBJ_USER_CERTIFICATE:
        !           272:                                userCertificate = object;
        !           273:                                break;
        !           274:                        case CRL_OBJ_REVOCATION_DATE:
        !           275:                                revoked = malloc_thing(revoked_t);
        !           276:                                revoked->serial = chunk_clone(userCertificate);
        !           277:                                revoked->date = asn1_parse_time(object, level);
        !           278:                                revoked->reason = CRL_REASON_UNSPECIFIED;
        !           279:                                this->revoked->insert_last(this->revoked, (void *)revoked);
        !           280:                                break;
        !           281:                        case CRL_OBJ_CRL_ENTRY_EXTN_ID:
        !           282:                        case CRL_OBJ_EXTN_ID:
        !           283:                                extnID = object;
        !           284:                                break;
        !           285:                        case CRL_OBJ_CRL_ENTRY_CRITICAL:
        !           286:                        case CRL_OBJ_CRITICAL:
        !           287:                                critical = object.len && *object.ptr;
        !           288:                                DBG2(DBG_ASN, "  %s", critical ? "TRUE" : "FALSE");
        !           289:                                break;
        !           290:                        case CRL_OBJ_CRL_ENTRY_EXTN_VALUE:
        !           291:                        case CRL_OBJ_EXTN_VALUE:
        !           292:                        {
        !           293:                                int extn_oid = asn1_known_oid(extnID);
        !           294: 
        !           295:                                switch (extn_oid)
        !           296:                                {
        !           297:                                        case OID_CRL_REASON_CODE:
        !           298:                                                if (revoked)
        !           299:                                                {
        !           300:                                                        if (object.len && *object.ptr == ASN1_ENUMERATED &&
        !           301:                                                                asn1_length(&object) == 1)
        !           302:                                                        {
        !           303:                                                                revoked->reason = *object.ptr;
        !           304:                                                        }
        !           305:                                                        DBG2(DBG_ASN, "  '%N'", crl_reason_names,
        !           306:                                                                 revoked->reason);
        !           307:                                                }
        !           308:                                                break;
        !           309:                                        case OID_AUTHORITY_KEY_ID:
        !           310:                                                chunk_free(&this->authKeyIdentifier);
        !           311:                                                this->authKeyIdentifier =
        !           312:                                                        x509_parse_authorityKeyIdentifier(
        !           313:                                                                        object, level, &this->authKeySerialNumber);
        !           314:                                                break;
        !           315:                                        case OID_CRL_NUMBER:
        !           316:                                                if (!asn1_parse_simple_object(&object, ASN1_INTEGER,
        !           317:                                                                                                          level, "crlNumber"))
        !           318:                                                {
        !           319:                                                        goto end;
        !           320:                                                }
        !           321:                                                this->crlNumber = object;
        !           322:                                                break;
        !           323:                                        case OID_FRESHEST_CRL:
        !           324:                                                if (!x509_parse_crlDistributionPoints(object, level,
        !           325:                                                                                                                          this->crl_uris))
        !           326:                                                {
        !           327:                                                        goto end;
        !           328:                                                }
        !           329:                                                break;
        !           330:                                        case OID_DELTA_CRL_INDICATOR:
        !           331:                                                if (!asn1_parse_simple_object(&object, ASN1_INTEGER,
        !           332:                                                                                                        level, "deltaCrlIndicator"))
        !           333:                                                {
        !           334:                                                        goto end;
        !           335:                                                }
        !           336:                                                this->baseCrlNumber = object;
        !           337:                                                break;
        !           338:                                        case OID_ISSUING_DIST_POINT:
        !           339:                                                /* TODO support of IssuingDistributionPoints */
        !           340:                                                break;
        !           341:                                        default:
        !           342:                                                if (critical && lib->settings->get_bool(lib->settings,
        !           343:                                                        "%s.x509.enforce_critical", TRUE, lib->ns))
        !           344:                                                {
        !           345:                                                        DBG1(DBG_ASN, "critical '%s' extension not supported",
        !           346:                                                                 (extn_oid == OID_UNKNOWN) ? "unknown" :
        !           347:                                                                 (char*)oid_names[extn_oid].name);
        !           348:                                                        goto end;
        !           349:                                                }
        !           350:                                                break;
        !           351:                                }
        !           352:                                break;
        !           353:                        }
        !           354:                        case CRL_OBJ_ALGORITHM:
        !           355:                        {
        !           356:                                INIT(this->scheme);
        !           357:                                if (!signature_params_parse(object, level, this->scheme))
        !           358:                                {
        !           359:                                        DBG1(DBG_ASN, "  unable to parse signature algorithm");
        !           360:                                        goto end;
        !           361:                                }
        !           362:                                if (!signature_params_equal(this->scheme, &sig_alg))
        !           363:                                {
        !           364:                                        DBG1(DBG_ASN, "  signature algorithms do not agree");
        !           365:                                        goto end;
        !           366:                                }
        !           367:                                break;
        !           368:                        }
        !           369:                        case CRL_OBJ_SIGNATURE:
        !           370:                                this->signature = chunk_skip(object, 1);
        !           371:                                break;
        !           372:                        default:
        !           373:                                break;
        !           374:                }
        !           375:        }
        !           376:        success = parser->success(parser);
        !           377: 
        !           378: end:
        !           379:        parser->destroy(parser);
        !           380:        signature_params_clear(&sig_alg);
        !           381:        return success;
        !           382: }
        !           383: 
        !           384: CALLBACK(filter, bool,
        !           385:        void *data, enumerator_t *orig, va_list args)
        !           386: {
        !           387:        revoked_t *revoked;
        !           388:        crl_reason_t *reason;
        !           389:        chunk_t *serial;
        !           390:        time_t *date;
        !           391: 
        !           392:        VA_ARGS_VGET(args, serial, date, reason);
        !           393: 
        !           394:        if (orig->enumerate(orig, &revoked))
        !           395:        {
        !           396:                if (serial)
        !           397:                {
        !           398:                        *serial = revoked->serial;
        !           399:                }
        !           400:                if (date)
        !           401:                {
        !           402:                        *date = revoked->date;
        !           403:                }
        !           404:                if (reason)
        !           405:                {
        !           406:                        *reason = revoked->reason;
        !           407:                }
        !           408:                return TRUE;
        !           409:        }
        !           410:        return FALSE;
        !           411: }
        !           412: 
        !           413: METHOD(crl_t, get_serial, chunk_t,
        !           414:        private_x509_crl_t *this)
        !           415: {
        !           416:        return this->crlNumber;
        !           417: }
        !           418: 
        !           419: METHOD(crl_t, get_authKeyIdentifier, chunk_t,
        !           420:        private_x509_crl_t *this)
        !           421: {
        !           422:        return this->authKeyIdentifier;
        !           423: }
        !           424: 
        !           425: METHOD(crl_t, is_delta_crl, bool,
        !           426:        private_x509_crl_t *this, chunk_t *base_crl)
        !           427: {
        !           428:        if (this->baseCrlNumber.len)
        !           429:        {
        !           430:                if (base_crl)
        !           431:                {
        !           432:                        *base_crl = this->baseCrlNumber;
        !           433:                }
        !           434:                return TRUE;
        !           435:        }
        !           436:        return FALSE;
        !           437: }
        !           438: 
        !           439: METHOD(crl_t, create_delta_crl_uri_enumerator, enumerator_t*,
        !           440:        private_x509_crl_t *this)
        !           441: {
        !           442:        return this->crl_uris->create_enumerator(this->crl_uris);
        !           443: }
        !           444: 
        !           445: METHOD(crl_t, create_enumerator, enumerator_t*,
        !           446:        private_x509_crl_t *this)
        !           447: {
        !           448:        return enumerator_create_filter(
        !           449:                                                                this->revoked->create_enumerator(this->revoked),
        !           450:                                                                filter, NULL, NULL);
        !           451: }
        !           452: 
        !           453: METHOD(certificate_t, get_type, certificate_type_t,
        !           454:        private_x509_crl_t *this)
        !           455: {
        !           456:        return CERT_X509_CRL;
        !           457: }
        !           458: 
        !           459: METHOD(certificate_t, get_issuer, identification_t*,
        !           460:        private_x509_crl_t *this)
        !           461: {
        !           462:        return this->issuer;
        !           463: }
        !           464: 
        !           465: METHOD(certificate_t, has_issuer, id_match_t,
        !           466:        private_x509_crl_t *this, identification_t *issuer)
        !           467: {
        !           468:        if (issuer->get_type(issuer) == ID_KEY_ID && this->authKeyIdentifier.ptr &&
        !           469:                chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer)))
        !           470:        {
        !           471:                return ID_MATCH_PERFECT;
        !           472:        }
        !           473:        return this->issuer->matches(this->issuer, issuer);
        !           474: }
        !           475: 
        !           476: METHOD(certificate_t, issued_by, bool,
        !           477:        private_x509_crl_t *this, certificate_t *issuer,
        !           478:        signature_params_t **scheme)
        !           479: {
        !           480:        public_key_t *key;
        !           481:        bool valid;
        !           482:        x509_t *x509 = (x509_t*)issuer;
        !           483:        chunk_t keyid = chunk_empty;
        !           484: 
        !           485:        /* check if issuer is an X.509 CA certificate */
        !           486:        if (issuer->get_type(issuer) != CERT_X509)
        !           487:        {
        !           488:                return FALSE;
        !           489:        }
        !           490:        if (!(x509->get_flags(x509) & (X509_CA | X509_CRL_SIGN)))
        !           491:        {
        !           492:                return FALSE;
        !           493:        }
        !           494: 
        !           495:        /* compare keyIdentifiers if available, otherwise use DNs */
        !           496:        if (this->authKeyIdentifier.ptr)
        !           497:        {
        !           498:                keyid = x509->get_subjectKeyIdentifier(x509);
        !           499:                if (keyid.len && !chunk_equals(keyid, this->authKeyIdentifier))
        !           500:                {
        !           501:                        return FALSE;
        !           502:                }
        !           503:        }
        !           504:        if (!keyid.len)
        !           505:        {
        !           506:                if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
        !           507:                {
        !           508:                        return FALSE;
        !           509:                }
        !           510:        }
        !           511: 
        !           512:        key = issuer->get_public_key(issuer);
        !           513:        if (!key)
        !           514:        {
        !           515:                return FALSE;
        !           516:        }
        !           517:        valid = key->verify(key, this->scheme->scheme, this->scheme->params,
        !           518:                                                this->tbsCertList, this->signature);
        !           519:        key->destroy(key);
        !           520:        if (valid && scheme)
        !           521:        {
        !           522:                *scheme = signature_params_clone(this->scheme);
        !           523:        }
        !           524:        return valid;
        !           525: }
        !           526: 
        !           527: METHOD(certificate_t, get_public_key, public_key_t*,
        !           528:        private_x509_crl_t *this)
        !           529: {
        !           530:        return NULL;
        !           531: }
        !           532: 
        !           533: METHOD(certificate_t, get_ref, certificate_t*,
        !           534:        private_x509_crl_t *this)
        !           535: {
        !           536:        ref_get(&this->ref);
        !           537:        return &this->public.crl.certificate;
        !           538: }
        !           539: 
        !           540: METHOD(certificate_t, get_validity, bool,
        !           541:        private_x509_crl_t *this, time_t *when,
        !           542:        time_t *not_before, time_t *not_after)
        !           543: {
        !           544:        time_t t = when ? *when : time(NULL);
        !           545: 
        !           546:        if (not_before)
        !           547:        {
        !           548:                *not_before = this->thisUpdate;
        !           549:        }
        !           550:        if (not_after)
        !           551:        {
        !           552:                *not_after = this->nextUpdate;
        !           553:        }
        !           554:        return (t >= this->thisUpdate && t <= this->nextUpdate);
        !           555: }
        !           556: 
        !           557: METHOD(certificate_t, get_encoding, bool,
        !           558:        private_x509_crl_t *this, cred_encoding_type_t type, chunk_t *encoding)
        !           559: {
        !           560:        if (type == CERT_ASN1_DER)
        !           561:        {
        !           562:                *encoding = chunk_clone(this->encoding);
        !           563:                return TRUE;
        !           564:        }
        !           565:        return lib->encoding->encode(lib->encoding, type, NULL, encoding,
        !           566:                                        CRED_PART_X509_CRL_ASN1_DER, this->encoding, CRED_PART_END);
        !           567: }
        !           568: 
        !           569: METHOD(certificate_t, equals, bool,
        !           570:        private_x509_crl_t *this, certificate_t *other)
        !           571: {
        !           572:        chunk_t encoding;
        !           573:        bool equal;
        !           574: 
        !           575:        if ((certificate_t*)this == other)
        !           576:        {
        !           577:                return TRUE;
        !           578:        }
        !           579:        if (other->equals == (void*)equals)
        !           580:        {       /* skip allocation if we have the same implementation */
        !           581:                return chunk_equals(this->encoding, ((private_x509_crl_t*)other)->encoding);
        !           582:        }
        !           583:        if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
        !           584:        {
        !           585:                return FALSE;
        !           586:        }
        !           587:        equal = chunk_equals(this->encoding, encoding);
        !           588:        free(encoding.ptr);
        !           589:        return equal;
        !           590: }
        !           591: 
        !           592: /**
        !           593:  * Destroy a revoked_t entry
        !           594:  */
        !           595: static void revoked_destroy(revoked_t *revoked)
        !           596: {
        !           597:        free(revoked->serial.ptr);
        !           598:        free(revoked);
        !           599: }
        !           600: 
        !           601: METHOD(certificate_t, destroy, void,
        !           602:        private_x509_crl_t *this)
        !           603: {
        !           604:        if (ref_put(&this->ref))
        !           605:        {
        !           606:                this->revoked->destroy_function(this->revoked, (void*)revoked_destroy);
        !           607:                this->crl_uris->destroy_function(this->crl_uris,
        !           608:                                                                                 (void*)x509_cdp_destroy);
        !           609:                signature_params_destroy(this->scheme);
        !           610:                DESTROY_IF(this->issuer);
        !           611:                free(this->authKeyIdentifier.ptr);
        !           612:                free(this->encoding.ptr);
        !           613:                free(this->critical_extension_oid.ptr);
        !           614:                if (this->generated)
        !           615:                {
        !           616:                        free(this->crlNumber.ptr);
        !           617:                        free(this->baseCrlNumber.ptr);
        !           618:                        free(this->signature.ptr);
        !           619:                        free(this->tbsCertList.ptr);
        !           620:                }
        !           621:                free(this);
        !           622:        }
        !           623: }
        !           624: 
        !           625: /**
        !           626:  * create an empty but initialized X.509 crl
        !           627:  */
        !           628: static private_x509_crl_t* create_empty(void)
        !           629: {
        !           630:        private_x509_crl_t *this;
        !           631: 
        !           632:        INIT(this,
        !           633:                .public = {
        !           634:                        .crl = {
        !           635:                                .certificate = {
        !           636:                                        .get_type = _get_type,
        !           637:                                        .get_subject = _get_issuer,
        !           638:                                        .get_issuer = _get_issuer,
        !           639:                                        .has_subject = _has_issuer,
        !           640:                                        .has_issuer = _has_issuer,
        !           641:                                        .issued_by = _issued_by,
        !           642:                                        .get_public_key = _get_public_key,
        !           643:                                        .get_validity = _get_validity,
        !           644:                                        .get_encoding = _get_encoding,
        !           645:                                        .equals = _equals,
        !           646:                                        .get_ref = _get_ref,
        !           647:                                        .destroy = _destroy,
        !           648:                                },
        !           649:                                .get_serial = _get_serial,
        !           650:                                .get_authKeyIdentifier = _get_authKeyIdentifier,
        !           651:                                .is_delta_crl = _is_delta_crl,
        !           652:                                .create_delta_crl_uri_enumerator = _create_delta_crl_uri_enumerator,
        !           653:                                .create_enumerator = _create_enumerator,
        !           654:                        },
        !           655:                },
        !           656:                .revoked = linked_list_create(),
        !           657:                .crl_uris = linked_list_create(),
        !           658:                .ref = 1,
        !           659:        );
        !           660:        return this;
        !           661: }
        !           662: 
        !           663: /**
        !           664:  * See header.
        !           665:  */
        !           666: x509_crl_t *x509_crl_load(certificate_type_t type, va_list args)
        !           667: {
        !           668:        chunk_t blob = chunk_empty;
        !           669: 
        !           670:        while (TRUE)
        !           671:        {
        !           672:                switch (va_arg(args, builder_part_t))
        !           673:                {
        !           674:                        case BUILD_BLOB_ASN1_DER:
        !           675:                                blob = va_arg(args, chunk_t);
        !           676:                                continue;
        !           677:                        case BUILD_END:
        !           678:                                break;
        !           679:                        default:
        !           680:                                return NULL;
        !           681:                }
        !           682:                break;
        !           683:        }
        !           684:        if (blob.ptr)
        !           685:        {
        !           686:                private_x509_crl_t *crl = create_empty();
        !           687: 
        !           688:                crl->encoding = chunk_clone(blob);
        !           689:                if (parse(crl))
        !           690:                {
        !           691:                        return &crl->public;
        !           692:                }
        !           693:                destroy(crl);
        !           694:        }
        !           695:        return NULL;
        !           696: };
        !           697: 
        !           698: /**
        !           699:  * Read certificate status from enumerator, copy to crl
        !           700:  */
        !           701: static void read_revoked(private_x509_crl_t *crl, enumerator_t *enumerator)
        !           702: {
        !           703:        revoked_t *revoked;
        !           704:        chunk_t serial;
        !           705:        time_t date;
        !           706:        crl_reason_t reason;
        !           707: 
        !           708:        while (enumerator->enumerate(enumerator, &serial, &date, &reason))
        !           709:        {
        !           710:                INIT(revoked,
        !           711:                        .serial = chunk_clone(serial),
        !           712:                        .date = date,
        !           713:                        .reason = reason,
        !           714:                );
        !           715:                crl->revoked->insert_last(crl->revoked, revoked);
        !           716:        }
        !           717: }
        !           718: 
        !           719: /**
        !           720:  * Generate CRL encoding, sign CRL
        !           721:  */
        !           722: static bool generate(private_x509_crl_t *this, certificate_t *cert,
        !           723:                                         private_key_t *key, hash_algorithm_t digest_alg)
        !           724: {
        !           725:        chunk_t extensions = chunk_empty, certList = chunk_empty, serial;
        !           726:        chunk_t crlDistributionPoints = chunk_empty, baseCrlNumber = chunk_empty;
        !           727:        chunk_t sig_scheme = chunk_empty, criticalExtension = chunk_empty;
        !           728:        enumerator_t *enumerator;
        !           729:        crl_reason_t reason;
        !           730:        time_t date;
        !           731:        x509_t *x509;
        !           732: 
        !           733:        x509 = (x509_t*)cert;
        !           734: 
        !           735:        this->issuer = cert->get_subject(cert);
        !           736:        this->issuer = this->issuer->clone(this->issuer);
        !           737: 
        !           738:        this->authKeyIdentifier = chunk_clone(x509->get_subjectKeyIdentifier(x509));
        !           739: 
        !           740:        /* select signature scheme, if not already specified */
        !           741:        if (!this->scheme)
        !           742:        {
        !           743:                INIT(this->scheme,
        !           744:                        .scheme = signature_scheme_from_oid(
        !           745:                                                                hasher_signature_algorithm_to_oid(digest_alg,
        !           746:                                                                                                key->get_type(key))),
        !           747:                );
        !           748:        }
        !           749:        if (this->scheme->scheme == SIGN_UNKNOWN)
        !           750:        {
        !           751:                return FALSE;
        !           752:        }
        !           753:        if (!signature_params_build(this->scheme, &sig_scheme))
        !           754:        {
        !           755:                return FALSE;
        !           756:        }
        !           757: 
        !           758:        enumerator = create_enumerator(this);
        !           759:        while (enumerator->enumerate(enumerator, &serial, &date, &reason))
        !           760:        {
        !           761:                chunk_t revoked, entry_ext = chunk_empty;
        !           762: 
        !           763:                if (reason != CRL_REASON_UNSPECIFIED)
        !           764:                {
        !           765:                        entry_ext = asn1_wrap(ASN1_SEQUENCE, "m",
        !           766:                                                        asn1_wrap(ASN1_SEQUENCE, "mm",
        !           767:                                                                asn1_build_known_oid(OID_CRL_REASON_CODE),
        !           768:                                                                asn1_wrap(ASN1_OCTET_STRING, "m",
        !           769:                                                                        asn1_wrap(ASN1_ENUMERATED, "c",
        !           770:                                                                                chunk_from_chars(reason)))));
        !           771:                }
        !           772:                revoked = asn1_wrap(ASN1_SEQUENCE, "mmm",
        !           773:                                                        asn1_integer("c", serial),
        !           774:                                                        asn1_from_time(&date, ASN1_UTCTIME),
        !           775:                                                        entry_ext);
        !           776:                certList = chunk_cat("mm", certList, revoked);
        !           777:        }
        !           778:        enumerator->destroy(enumerator);
        !           779: 
        !           780:        crlDistributionPoints = x509_build_crlDistributionPoints(this->crl_uris,
        !           781:                                                                                                                         OID_FRESHEST_CRL);
        !           782: 
        !           783:        if (this->baseCrlNumber.len)
        !           784:        {
        !           785:                baseCrlNumber =  asn1_wrap(ASN1_SEQUENCE, "mmm",
        !           786:                                                        asn1_build_known_oid(OID_DELTA_CRL_INDICATOR),
        !           787:                                                        asn1_wrap(ASN1_BOOLEAN, "c",
        !           788:                                                                chunk_from_chars(0xFF)),
        !           789:                                                        asn1_wrap(ASN1_OCTET_STRING, "m",
        !           790:                                                                asn1_integer("c", this->baseCrlNumber)));
        !           791:        }
        !           792: 
        !           793:        if (this->critical_extension_oid.len > 0)
        !           794:        {
        !           795:                criticalExtension = asn1_wrap(ASN1_SEQUENCE, "mmm",
        !           796:                                        asn1_simple_object(ASN1_OID, this->critical_extension_oid),
        !           797:                                        asn1_simple_object(ASN1_BOOLEAN, chunk_from_chars(0xFF)),
        !           798:                                        asn1_simple_object(ASN1_OCTET_STRING, chunk_empty));
        !           799:        }
        !           800: 
        !           801:        extensions = asn1_wrap(ASN1_CONTEXT_C_0, "m",
        !           802:                                        asn1_wrap(ASN1_SEQUENCE, "mmmmm",
        !           803:                                                asn1_wrap(ASN1_SEQUENCE, "mm",
        !           804:                                                        asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
        !           805:                                                        asn1_wrap(ASN1_OCTET_STRING, "m",
        !           806:                                                                asn1_wrap(ASN1_SEQUENCE, "m",
        !           807:                                                                        asn1_wrap(ASN1_CONTEXT_S_0, "c",
        !           808:                                                                                          this->authKeyIdentifier)))),
        !           809:                                                asn1_wrap(ASN1_SEQUENCE, "mm",
        !           810:                                                        asn1_build_known_oid(OID_CRL_NUMBER),
        !           811:                                                        asn1_wrap(ASN1_OCTET_STRING, "m",
        !           812:                                                                asn1_integer("c", this->crlNumber))),
        !           813:                                                crlDistributionPoints, baseCrlNumber,
        !           814:                                                criticalExtension));
        !           815: 
        !           816:        this->tbsCertList = asn1_wrap(ASN1_SEQUENCE, "cccmmmm",
        !           817:                                                        ASN1_INTEGER_1,
        !           818:                                                        sig_scheme,
        !           819:                                                        this->issuer->get_encoding(this->issuer),
        !           820:                                                        asn1_from_time(&this->thisUpdate, ASN1_UTCTIME),
        !           821:                                                        asn1_from_time(&this->nextUpdate, ASN1_UTCTIME),
        !           822:                                                        asn1_wrap(ASN1_SEQUENCE, "m", certList),
        !           823:                                                        extensions);
        !           824: 
        !           825:        if (!key->sign(key, this->scheme->scheme, this->scheme->params,
        !           826:                                   this->tbsCertList, &this->signature))
        !           827:        {
        !           828:                chunk_free(&sig_scheme);
        !           829:                return FALSE;
        !           830:        }
        !           831:        this->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm",
        !           832:                                                        this->tbsCertList,
        !           833:                                                        sig_scheme,
        !           834:                                                        asn1_bitstring("c", this->signature));
        !           835:        return TRUE;
        !           836: }
        !           837: 
        !           838: /**
        !           839:  * See header.
        !           840:  */
        !           841: x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args)
        !           842: {
        !           843:        hash_algorithm_t digest_alg = HASH_SHA1;
        !           844:        private_x509_crl_t *crl;
        !           845:        certificate_t *cert = NULL;
        !           846:        private_key_t *key = NULL;
        !           847: 
        !           848:        crl = create_empty();
        !           849:        crl->generated = TRUE;
        !           850:        while (TRUE)
        !           851:        {
        !           852:                builder_part_t part = va_arg(args, builder_part_t);
        !           853: 
        !           854:                switch (part)
        !           855:                {
        !           856:                        case BUILD_SIGNING_KEY:
        !           857:                                key = va_arg(args, private_key_t*);
        !           858:                                continue;
        !           859:                        case BUILD_SIGNING_CERT:
        !           860:                                cert = va_arg(args, certificate_t*);
        !           861:                                continue;
        !           862:                        case BUILD_NOT_BEFORE_TIME:
        !           863:                                crl->thisUpdate = va_arg(args, time_t);
        !           864:                                continue;
        !           865:                        case BUILD_NOT_AFTER_TIME:
        !           866:                                crl->nextUpdate = va_arg(args, time_t);
        !           867:                                continue;
        !           868:                        case BUILD_SERIAL:
        !           869:                                crl->crlNumber = va_arg(args, chunk_t);
        !           870:                                crl->crlNumber = chunk_clone(crl->crlNumber);
        !           871:                                continue;
        !           872:                        case BUILD_SIGNATURE_SCHEME:
        !           873:                                crl->scheme = va_arg(args, signature_params_t*);
        !           874:                                crl->scheme = signature_params_clone(crl->scheme);
        !           875:                                continue;
        !           876:                        case BUILD_DIGEST_ALG:
        !           877:                                digest_alg = va_arg(args, int);
        !           878:                                continue;
        !           879:                        case BUILD_REVOKED_ENUMERATOR:
        !           880:                                read_revoked(crl, va_arg(args, enumerator_t*));
        !           881:                                continue;
        !           882:                        case BUILD_BASE_CRL:
        !           883:                                crl->baseCrlNumber = va_arg(args, chunk_t);
        !           884:                                crl->baseCrlNumber = chunk_clone(crl->baseCrlNumber);
        !           885:                                break;
        !           886:                        case BUILD_CRL_DISTRIBUTION_POINTS:
        !           887:                        {
        !           888:                                enumerator_t *enumerator;
        !           889:                                linked_list_t *list;
        !           890:                                x509_cdp_t *in, *cdp;
        !           891: 
        !           892:                                list = va_arg(args, linked_list_t*);
        !           893:                                enumerator = list->create_enumerator(list);
        !           894:                                while (enumerator->enumerate(enumerator, &in))
        !           895:                                {
        !           896:                                        INIT(cdp,
        !           897:                                                .uri = strdup(in->uri),
        !           898:                                                .issuer = in->issuer ? in->issuer->clone(in->issuer) : NULL,
        !           899:                                        );
        !           900:                                        crl->crl_uris->insert_last(crl->crl_uris, cdp);
        !           901:                                }
        !           902:                                enumerator->destroy(enumerator);
        !           903:                                continue;
        !           904:                        }
        !           905:                        case BUILD_CRITICAL_EXTENSION:
        !           906:                                crl->critical_extension_oid = chunk_clone(va_arg(args, chunk_t));
        !           907:                                continue;
        !           908:                        case BUILD_END:
        !           909:                                break;
        !           910:                        default:
        !           911:                                destroy(crl);
        !           912:                                return NULL;
        !           913:                }
        !           914:                break;
        !           915:        }
        !           916: 
        !           917:        if (key && cert && cert->get_type(cert) == CERT_X509 &&
        !           918:                generate(crl, cert, key, digest_alg))
        !           919:        {
        !           920:                return &crl->public;
        !           921:        }
        !           922:        destroy(crl);
        !           923:        return NULL;
        !           924: }

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