Annotation of embedaddon/strongswan/src/libstrongswan/plugins/x509/x509_crl.c, revision 1.1.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>