Annotation of embedaddon/strongswan/src/libstrongswan/plugins/openssl/openssl_x509.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2011-2017 Tobias Brunner
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
        !             5:  * Copyright (C) 2010 Martin Willi
        !             6:  * Copyright (C) 2010 revosec AG
        !             7:  *
        !             8:  * This program is free software; you can redistribute it and/or modify it
        !             9:  * under the terms of the GNU General Public License as published by the
        !            10:  * Free Software Foundation; either version 2 of the License, or (at your
        !            11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            12:  *
        !            13:  * This program is distributed in the hope that it will be useful, but
        !            14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            16:  * for more details.
        !            17:  */
        !            18: 
        !            19: /*
        !            20:  * Copyright (C) 2013 Michael Rossberg
        !            21:  * Copyright (C) 2013 Technische Universität Ilmenau
        !            22:  *
        !            23:  * Copyright (C) 2010 secunet Security Networks AG
        !            24:  * Copyright (C) 2010 Thomas Egerer
        !            25:  *
        !            26:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !            27:  * of this software and associated documentation files (the "Software"), to deal
        !            28:  * in the Software without restriction, including without limitation the rights
        !            29:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            30:  * copies of the Software, and to permit persons to whom the Software is
        !            31:  * furnished to do so, subject to the following conditions:
        !            32:  *
        !            33:  * The above copyright notice and this permission notice shall be included in
        !            34:  * all copies or substantial portions of the Software.
        !            35:  *
        !            36:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            37:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            38:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        !            39:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            40:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            41:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            42:  * THE SOFTWARE.
        !            43:  */
        !            44: 
        !            45: #define _GNU_SOURCE
        !            46: #include <stdio.h>
        !            47: #include <openssl/x509.h>
        !            48: #include <openssl/x509v3.h>
        !            49: 
        !            50: #include "openssl_x509.h"
        !            51: #include "openssl_util.h"
        !            52: 
        !            53: #include <utils/debug.h>
        !            54: #include <asn1/oid.h>
        !            55: #include <collections/linked_list.h>
        !            56: #include <selectors/traffic_selector.h>
        !            57: 
        !            58: /* IP Addr block extension support was introduced with 0.9.8e */
        !            59: #if OPENSSL_VERSION_NUMBER < 0x0090805fL
        !            60: #define OPENSSL_NO_RFC3779
        !            61: #endif
        !            62: 
        !            63: /* added with 1.0.2 */
        !            64: #if OPENSSL_VERSION_NUMBER < 0x10002000L
        !            65: static inline void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509 *x) {
        !            66:        if (psig) { *psig = x->signature; }
        !            67:        if (palg) { *palg = x->sig_alg; }
        !            68: }
        !            69: #endif
        !            70: 
        !            71: /* added with 1.1.0 when X509 etc. was made opaque */
        !            72: #if OPENSSL_VERSION_NUMBER < 0x10100000L
        !            73: #define X509_get0_extensions(x509) ({ (x509)->cert_info->extensions; })
        !            74: #define X509_get0_tbs_sigalg(x509) ({ (x509)->cert_info->signature; })
        !            75: #define X509_ALGOR_get0(oid, ppt, ppv, alg) ({ *(oid) = (alg)->algorithm; })
        !            76: #define X509_PUBKEY_get0_param(oid, pk, len, pa, pub) X509_ALGOR_get0(oid, NULL, NULL, (pub)->algor)
        !            77: #define X509v3_addr_get_afi v3_addr_get_afi
        !            78: #define X509v3_addr_get_range v3_addr_get_range
        !            79: #define X509v3_addr_is_canonical v3_addr_is_canonical
        !            80: #define X509_get0_notBefore X509_get_notBefore
        !            81: #define X509_get0_notAfter X509_get_notAfter
        !            82: #endif
        !            83: 
        !            84: typedef struct private_openssl_x509_t private_openssl_x509_t;
        !            85: 
        !            86: /**
        !            87:  * Private data of an openssl_x509_t object.
        !            88:  */
        !            89: struct private_openssl_x509_t {
        !            90: 
        !            91:        /**
        !            92:         * Public openssl_x509_t interface.
        !            93:         */
        !            94:        openssl_x509_t public;
        !            95: 
        !            96:        /**
        !            97:         * OpenSSL certificate representation
        !            98:         */
        !            99:        X509 *x509;
        !           100: 
        !           101:        /**
        !           102:         * DER encoded certificate
        !           103:         */
        !           104:        chunk_t encoding;
        !           105: 
        !           106:        /**
        !           107:         * SHA1 hash of the certificate
        !           108:         */
        !           109:        chunk_t hash;
        !           110: 
        !           111:        /**
        !           112:         * X509 flags
        !           113:         */
        !           114:        x509_flag_t flags;
        !           115: 
        !           116:        /**
        !           117:         * Pathlen constraint
        !           118:         */
        !           119:        u_char pathlen;
        !           120: 
        !           121:        /**
        !           122:         * certificate subject
        !           123:         */
        !           124:        identification_t *subject;
        !           125: 
        !           126:        /**
        !           127:         * certificate issuer
        !           128:         */
        !           129:        identification_t *issuer;
        !           130: 
        !           131:        /**
        !           132:         * Certificates public key
        !           133:         */
        !           134:        public_key_t *pubkey;
        !           135: 
        !           136:        /**
        !           137:         * subjectKeyIdentifier as read from cert
        !           138:         */
        !           139:        chunk_t subjectKeyIdentifier;
        !           140: 
        !           141:        /**
        !           142:         * authorityKeyIdentifier as read from cert
        !           143:         */
        !           144:        chunk_t authKeyIdentifier;
        !           145: 
        !           146:        /**
        !           147:         * Start time of certificate validity
        !           148:         */
        !           149:        time_t notBefore;
        !           150: 
        !           151:        /**
        !           152:         * End time of certificate validity
        !           153:         */
        !           154:        time_t notAfter;
        !           155: 
        !           156:        /**
        !           157:         * Signature scheme of the certificate
        !           158:         */
        !           159:        signature_params_t *scheme;
        !           160: 
        !           161:        /**
        !           162:         * subjectAltNames
        !           163:         */
        !           164:        linked_list_t *subjectAltNames;
        !           165: 
        !           166:        /**
        !           167:         * issuerAltNames
        !           168:         */
        !           169:        linked_list_t *issuerAltNames;
        !           170: 
        !           171:        /**
        !           172:         * List of CRL URIs, as x509_cdp_t
        !           173:         */
        !           174:        linked_list_t *crl_uris;
        !           175: 
        !           176:        /**
        !           177:         * List of OCSP URIs
        !           178:         */
        !           179:        linked_list_t *ocsp_uris;
        !           180: 
        !           181:        /**
        !           182:         * List of ipAddrBlocks as traffic_selector_t
        !           183:         */
        !           184:        linked_list_t *ipAddrBlocks;
        !           185: 
        !           186: 
        !           187:        /**
        !           188:         * References to this cert
        !           189:         */
        !           190:        refcount_t ref;
        !           191: };
        !           192: 
        !           193: /**
        !           194:  * Convert a GeneralName to an identification_t.
        !           195:  */
        !           196: static identification_t *general_name2id(GENERAL_NAME *name)
        !           197: {
        !           198:        if (!name)
        !           199:        {
        !           200:                return NULL;
        !           201:        }
        !           202:        switch (name->type)
        !           203:        {
        !           204:                case GEN_EMAIL:
        !           205:                        return identification_create_from_encoding(ID_RFC822_ADDR,
        !           206:                                        openssl_asn1_str2chunk(name->d.rfc822Name));
        !           207:                case GEN_DNS:
        !           208:                        return identification_create_from_encoding(ID_FQDN,
        !           209:                                        openssl_asn1_str2chunk(name->d.dNSName));
        !           210:                case GEN_URI:
        !           211:                        return identification_create_from_encoding(ID_DER_ASN1_GN_URI,
        !           212:                                        openssl_asn1_str2chunk(name->d.uniformResourceIdentifier));
        !           213:                case GEN_IPADD:
        !           214:                {
        !           215:                        chunk_t chunk = openssl_asn1_str2chunk(name->d.iPAddress);
        !           216:                        if (chunk.len == 4)
        !           217:                        {
        !           218:                                return identification_create_from_encoding(ID_IPV4_ADDR, chunk);
        !           219:                        }
        !           220:                        if (chunk.len == 16)
        !           221:                        {
        !           222:                                return identification_create_from_encoding(ID_IPV6_ADDR, chunk);
        !           223:                        }
        !           224:                        return NULL;
        !           225:                }
        !           226:                case GEN_DIRNAME :
        !           227:                        return openssl_x509_name2id(name->d.directoryName);
        !           228:                case GEN_OTHERNAME:
        !           229:                        if (OBJ_obj2nid(name->d.otherName->type_id) == NID_ms_upn &&
        !           230:                                name->d.otherName->value->type == V_ASN1_UTF8STRING)
        !           231:                        {
        !           232:                                return identification_create_from_encoding(ID_RFC822_ADDR,
        !           233:                                                        openssl_asn1_str2chunk(
        !           234:                                                                name->d.otherName->value->value.utf8string));
        !           235:                        }
        !           236:                        return NULL;
        !           237:                default:
        !           238:                        return NULL;
        !           239:        }
        !           240: }
        !           241: 
        !           242: METHOD(x509_t, get_flags, x509_flag_t,
        !           243:        private_openssl_x509_t *this)
        !           244: {
        !           245:        return this->flags;
        !           246: }
        !           247: 
        !           248: METHOD(x509_t, get_serial, chunk_t,
        !           249:        private_openssl_x509_t *this)
        !           250: {
        !           251:        return openssl_asn1_str2chunk(X509_get_serialNumber(this->x509));
        !           252: }
        !           253: 
        !           254: METHOD(x509_t, get_subjectKeyIdentifier, chunk_t,
        !           255:        private_openssl_x509_t *this)
        !           256: {
        !           257:        chunk_t fingerprint;
        !           258: 
        !           259:        if (this->subjectKeyIdentifier.len)
        !           260:        {
        !           261:                return this->subjectKeyIdentifier;
        !           262:        }
        !           263:        if (this->pubkey->get_fingerprint(this->pubkey, KEYID_PUBKEY_SHA1,
        !           264:                                                                          &fingerprint))
        !           265:        {
        !           266:                return fingerprint;
        !           267:        }
        !           268:        return chunk_empty;
        !           269: }
        !           270: 
        !           271: METHOD(x509_t, get_authKeyIdentifier, chunk_t,
        !           272:        private_openssl_x509_t *this)
        !           273: {
        !           274:        if (this->authKeyIdentifier.len)
        !           275:        {
        !           276:                return this->authKeyIdentifier;
        !           277:        }
        !           278:        return chunk_empty;
        !           279: }
        !           280: 
        !           281: METHOD(x509_t, get_constraint, u_int,
        !           282:        private_openssl_x509_t *this, x509_constraint_t type)
        !           283: {
        !           284:        switch (type)
        !           285:        {
        !           286:                case X509_PATH_LEN:
        !           287:                        return this->pathlen;
        !           288:                default:
        !           289:                        return X509_NO_CONSTRAINT;
        !           290:        }
        !           291: }
        !           292: 
        !           293: METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
        !           294:        private_openssl_x509_t *this)
        !           295: {
        !           296:        return this->subjectAltNames->create_enumerator(this->subjectAltNames);
        !           297: }
        !           298: 
        !           299: METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*,
        !           300:        private_openssl_x509_t *this)
        !           301: {
        !           302:        return this->crl_uris->create_enumerator(this->crl_uris);
        !           303: }
        !           304: 
        !           305: METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
        !           306:        private_openssl_x509_t *this)
        !           307: {
        !           308:        return this->ocsp_uris->create_enumerator(this->ocsp_uris);
        !           309: }
        !           310: 
        !           311: METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
        !           312:        private_openssl_x509_t *this)
        !           313: {
        !           314:        return this->ipAddrBlocks->create_enumerator(this->ipAddrBlocks);
        !           315: }
        !           316: 
        !           317: METHOD(certificate_t, get_type, certificate_type_t,
        !           318:        private_openssl_x509_t *this)
        !           319: {
        !           320:        return CERT_X509;
        !           321: }
        !           322: 
        !           323: METHOD(certificate_t, get_subject, identification_t*,
        !           324:        private_openssl_x509_t *this)
        !           325: {
        !           326:        return this->subject;
        !           327: }
        !           328: 
        !           329: METHOD(certificate_t, get_issuer, identification_t*,
        !           330:        private_openssl_x509_t *this)
        !           331: {
        !           332:        return this->issuer;
        !           333: }
        !           334: 
        !           335: METHOD(certificate_t, has_subject, id_match_t,
        !           336:        private_openssl_x509_t *this, identification_t *subject)
        !           337: {
        !           338:        identification_t *current;
        !           339:        enumerator_t *enumerator;
        !           340:        id_match_t match, best;
        !           341:        chunk_t encoding;
        !           342: 
        !           343:        if (subject->get_type(subject) == ID_KEY_ID)
        !           344:        {
        !           345:                encoding = subject->get_encoding(subject);
        !           346: 
        !           347:                if (chunk_equals(this->hash, encoding))
        !           348:                {
        !           349:                        return ID_MATCH_PERFECT;
        !           350:                }
        !           351:                if (this->subjectKeyIdentifier.len &&
        !           352:                        chunk_equals(this->subjectKeyIdentifier, encoding))
        !           353:                {
        !           354:                        return ID_MATCH_PERFECT;
        !           355:                }
        !           356:                if (this->pubkey &&
        !           357:                        this->pubkey->has_fingerprint(this->pubkey, encoding))
        !           358:                {
        !           359:                        return ID_MATCH_PERFECT;
        !           360:                }
        !           361:                if (chunk_equals(get_serial(this), encoding))
        !           362:                {
        !           363:                        return ID_MATCH_PERFECT;
        !           364:                }
        !           365:        }
        !           366:        best = this->subject->matches(this->subject, subject);
        !           367:        enumerator = create_subjectAltName_enumerator(this);
        !           368:        while (enumerator->enumerate(enumerator, &current))
        !           369:        {
        !           370:                match = current->matches(current, subject);
        !           371:                if (match > best)
        !           372:                {
        !           373:                        best = match;
        !           374:                }
        !           375:        }
        !           376:        enumerator->destroy(enumerator);
        !           377:        return best;
        !           378: }
        !           379: 
        !           380: METHOD(certificate_t, has_issuer, id_match_t,
        !           381:        private_openssl_x509_t *this, identification_t *issuer)
        !           382: {
        !           383:        /* issuerAltNames currently not supported */
        !           384:        return this->issuer->matches(this->issuer, issuer);
        !           385: }
        !           386: 
        !           387: METHOD(certificate_t, issued_by, bool,
        !           388:        private_openssl_x509_t *this, certificate_t *issuer,
        !           389:        signature_params_t **scheme)
        !           390: {
        !           391:        public_key_t *key;
        !           392:        bool valid;
        !           393:        x509_t *x509 = (x509_t*)issuer;
        !           394: #if OPENSSL_VERSION_NUMBER >= 0x10100000L
        !           395:        const ASN1_BIT_STRING *sig;
        !           396: #else
        !           397:        ASN1_BIT_STRING *sig;
        !           398: #endif
        !           399:        chunk_t tbs;
        !           400: 
        !           401:        if (&this->public.x509.interface == issuer)
        !           402:        {
        !           403:                if (this->flags & X509_SELF_SIGNED)
        !           404:                {
        !           405:                        valid = TRUE;
        !           406:                        goto out;
        !           407:                }
        !           408:        }
        !           409:        else
        !           410:        {
        !           411:                if (issuer->get_type(issuer) != CERT_X509)
        !           412:                {
        !           413:                        return FALSE;
        !           414:                }
        !           415:                if (!(x509->get_flags(x509) & X509_CA))
        !           416:                {
        !           417:                        return FALSE;
        !           418:                }
        !           419:        }
        !           420:        if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
        !           421:        {
        !           422:                return FALSE;
        !           423:        }
        !           424:        key = issuer->get_public_key(issuer);
        !           425:        if (!key)
        !           426:        {
        !           427:                return FALSE;
        !           428:        }
        !           429:        /* i2d_re_X509_tbs() was added with 1.1.0 when X509 was made opaque */
        !           430: #if OPENSSL_VERSION_NUMBER >= 0x10100000L
        !           431:        tbs = openssl_i2chunk(re_X509_tbs, this->x509);
        !           432: #else
        !           433:        tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
        !           434: #endif
        !           435:        X509_get0_signature(&sig, NULL, this->x509);
        !           436:        valid = key->verify(key, this->scheme->scheme, this->scheme->params, tbs,
        !           437:                                                openssl_asn1_str2chunk(sig));
        !           438:        free(tbs.ptr);
        !           439:        key->destroy(key);
        !           440: 
        !           441: out:
        !           442:        if (valid && scheme)
        !           443:        {
        !           444:                *scheme = signature_params_clone(this->scheme);
        !           445:        }
        !           446:        return valid;
        !           447: }
        !           448: 
        !           449: METHOD(certificate_t, get_public_key, public_key_t*,
        !           450:        private_openssl_x509_t *this)
        !           451: {
        !           452:        return this->pubkey->get_ref(this->pubkey);
        !           453: }
        !           454: 
        !           455: METHOD(certificate_t, get_validity, bool,
        !           456:        private_openssl_x509_t *this,
        !           457:        time_t *when, time_t *not_before, time_t *not_after)
        !           458: {
        !           459:        time_t t;
        !           460: 
        !           461:        if (when)
        !           462:        {
        !           463:                t = *when;
        !           464:        }
        !           465:        else
        !           466:        {
        !           467:                t = time(NULL);
        !           468:        }
        !           469:        if (not_before)
        !           470:        {
        !           471:                *not_before = this->notBefore;
        !           472:        }
        !           473:        if (not_after)
        !           474:        {
        !           475:                *not_after = this->notAfter;
        !           476:        }
        !           477:        return (t >= this->notBefore && t <= this->notAfter);
        !           478: }
        !           479: 
        !           480: METHOD(certificate_t, get_encoding, bool,
        !           481:        private_openssl_x509_t *this, cred_encoding_type_t type, chunk_t *encoding)
        !           482: {
        !           483:        if (type == CERT_ASN1_DER)
        !           484:        {
        !           485:                *encoding = chunk_clone(this->encoding);
        !           486:                return TRUE;
        !           487:        }
        !           488:        return lib->encoding->encode(lib->encoding, type, NULL, encoding,
        !           489:                                                CRED_PART_X509_ASN1_DER, this->encoding, CRED_PART_END);
        !           490: }
        !           491: 
        !           492: 
        !           493: METHOD(certificate_t, equals, bool,
        !           494:        private_openssl_x509_t *this, certificate_t *other)
        !           495: {
        !           496:        chunk_t encoding;
        !           497:        bool equal;
        !           498: 
        !           499:        if (this == (private_openssl_x509_t*)other)
        !           500:        {
        !           501:                return TRUE;
        !           502:        }
        !           503:        if (other->get_type(other) != CERT_X509)
        !           504:        {
        !           505:                return FALSE;
        !           506:        }
        !           507:        if (other->equals == (void*)equals)
        !           508:        {       /* skip allocation if we have the same implementation */
        !           509:                encoding = ((private_openssl_x509_t*)other)->encoding;
        !           510:                return chunk_equals(this->encoding, encoding);
        !           511:        }
        !           512:        if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
        !           513:        {
        !           514:                return FALSE;
        !           515:        }
        !           516:        equal = chunk_equals(this->encoding, encoding);
        !           517:        free(encoding.ptr);
        !           518:        return equal;
        !           519: }
        !           520: 
        !           521: METHOD(certificate_t, get_ref, certificate_t*,
        !           522:        private_openssl_x509_t *this)
        !           523: {
        !           524:        ref_get(&this->ref);
        !           525:        return &this->public.x509.interface;
        !           526: }
        !           527: 
        !           528: METHOD(certificate_t, destroy, void,
        !           529:        private_openssl_x509_t *this)
        !           530: {
        !           531:        if (ref_put(&this->ref))
        !           532:        {
        !           533:                if (this->x509)
        !           534:                {
        !           535:                        X509_free(this->x509);
        !           536:                }
        !           537:                signature_params_destroy(this->scheme);
        !           538:                DESTROY_IF(this->subject);
        !           539:                DESTROY_IF(this->issuer);
        !           540:                DESTROY_IF(this->pubkey);
        !           541:                free(this->subjectKeyIdentifier.ptr);
        !           542:                free(this->authKeyIdentifier.ptr);
        !           543:                free(this->encoding.ptr);
        !           544:                free(this->hash.ptr);
        !           545:                this->subjectAltNames->destroy_offset(this->subjectAltNames,
        !           546:                                                                                offsetof(identification_t, destroy));
        !           547:                this->issuerAltNames->destroy_offset(this->issuerAltNames,
        !           548:                                                                                offsetof(identification_t, destroy));
        !           549:                this->crl_uris->destroy_function(this->crl_uris,
        !           550:                                                                                 (void*)x509_cdp_destroy);
        !           551:                this->ocsp_uris->destroy_function(this->ocsp_uris, free);
        !           552:                this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks,
        !           553:                                                                                offsetof(traffic_selector_t, destroy));
        !           554:                free(this);
        !           555:        }
        !           556: }
        !           557: 
        !           558: /**
        !           559:  * Create an empty certificate
        !           560:  */
        !           561: static private_openssl_x509_t *create_empty()
        !           562: {
        !           563:        private_openssl_x509_t *this;
        !           564: 
        !           565:        INIT(this,
        !           566:                .public = {
        !           567:                        .x509 = {
        !           568:                                .interface = {
        !           569:                                        .get_type = _get_type,
        !           570:                                        .get_subject = _get_subject,
        !           571:                                        .get_issuer = _get_issuer,
        !           572:                                        .has_subject = _has_subject,
        !           573:                                        .has_issuer = _has_issuer,
        !           574:                                        .issued_by = _issued_by,
        !           575:                                        .get_public_key = _get_public_key,
        !           576:                                        .get_validity = _get_validity,
        !           577:                                        .get_encoding = _get_encoding,
        !           578:                                        .equals = _equals,
        !           579:                                        .get_ref = _get_ref,
        !           580:                                        .destroy = _destroy,
        !           581:                                },
        !           582:                                .get_flags = _get_flags,
        !           583:                                .get_serial = _get_serial,
        !           584:                                .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
        !           585:                                .get_authKeyIdentifier = _get_authKeyIdentifier,
        !           586:                                .get_constraint = _get_constraint,
        !           587:                                .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
        !           588:                                .create_crl_uri_enumerator = _create_crl_uri_enumerator,
        !           589:                                .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
        !           590:                                .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
        !           591:                                .create_name_constraint_enumerator = (void*)enumerator_create_empty,
        !           592:                                .create_cert_policy_enumerator = (void*)enumerator_create_empty,
        !           593:                                .create_policy_mapping_enumerator = (void*)enumerator_create_empty,
        !           594:                        },
        !           595:                },
        !           596:                .subjectAltNames = linked_list_create(),
        !           597:                .issuerAltNames = linked_list_create(),
        !           598:                .crl_uris = linked_list_create(),
        !           599:                .ocsp_uris = linked_list_create(),
        !           600:                .ipAddrBlocks = linked_list_create(),
        !           601:                .pathlen = X509_NO_CONSTRAINT,
        !           602:                .ref = 1,
        !           603:        );
        !           604: 
        !           605:        return this;
        !           606: }
        !           607: 
        !           608: /**
        !           609:  * parse an extension containing GENERAL_NAMES into a list
        !           610:  */
        !           611: static bool parse_generalNames_ext(linked_list_t *list,
        !           612:                                                                   X509_EXTENSION *ext)
        !           613: {
        !           614:        GENERAL_NAMES *names;
        !           615:        GENERAL_NAME *name;
        !           616:        identification_t *id;
        !           617:        int i, num;
        !           618: 
        !           619:        names = X509V3_EXT_d2i(ext);
        !           620:        if (!names)
        !           621:        {
        !           622:                return FALSE;
        !           623:        }
        !           624: 
        !           625:        num = sk_GENERAL_NAME_num(names);
        !           626:        for (i = 0; i < num; i++)
        !           627:        {
        !           628:                name = sk_GENERAL_NAME_value(names, i);
        !           629:                id = general_name2id(name);
        !           630:                if (id)
        !           631:                {
        !           632:                        list->insert_last(list, id);
        !           633:                }
        !           634:                GENERAL_NAME_free(name);
        !           635:        }
        !           636:        sk_GENERAL_NAME_free(names);
        !           637:        return TRUE;
        !           638: }
        !           639: 
        !           640: /**
        !           641:  * parse basic constraints
        !           642:  */
        !           643: static bool parse_basicConstraints_ext(private_openssl_x509_t *this,
        !           644:                                                                           X509_EXTENSION *ext)
        !           645: {
        !           646:        BASIC_CONSTRAINTS *constraints;
        !           647:        long pathlen;
        !           648: 
        !           649:        constraints = (BASIC_CONSTRAINTS*)X509V3_EXT_d2i(ext);
        !           650:        if (constraints)
        !           651:        {
        !           652:                if (constraints->ca)
        !           653:                {
        !           654:                        this->flags |= X509_CA;
        !           655:                }
        !           656:                if (constraints->pathlen)
        !           657:                {
        !           658: 
        !           659:                        pathlen = ASN1_INTEGER_get(constraints->pathlen);
        !           660:                        this->pathlen = (pathlen >= 0 && pathlen < 128) ?
        !           661:                                                         pathlen : X509_NO_CONSTRAINT;
        !           662:                }
        !           663:                BASIC_CONSTRAINTS_free(constraints);
        !           664:                return TRUE;
        !           665:        }
        !           666:        return FALSE;
        !           667: }
        !           668: 
        !           669: /**
        !           670:  * parse key usage
        !           671:  */
        !           672: static bool parse_keyUsage_ext(private_openssl_x509_t *this,
        !           673:                                                           X509_EXTENSION *ext)
        !           674: {
        !           675:        ASN1_BIT_STRING *usage;
        !           676: 
        !           677:        /* to be compliant with RFC 4945 specific KUs have to be included */
        !           678:        this->flags &= ~X509_IKE_COMPLIANT;
        !           679: 
        !           680:        usage = X509V3_EXT_d2i(ext);
        !           681:        if (usage)
        !           682:        {
        !           683:                if (usage->length > 0)
        !           684:                {
        !           685:                        int flags = usage->data[0];
        !           686:                        if (usage->length > 1)
        !           687:                        {
        !           688:                                flags |= usage->data[1] << 8;
        !           689:                        }
        !           690:                        if (flags & X509v3_KU_CRL_SIGN)
        !           691:                        {
        !           692:                                this->flags |= X509_CRL_SIGN;
        !           693:                        }
        !           694:                        if (flags & X509v3_KU_DIGITAL_SIGNATURE ||
        !           695:                                flags & X509v3_KU_NON_REPUDIATION)
        !           696:                        {
        !           697:                                this->flags |= X509_IKE_COMPLIANT;
        !           698:                        }
        !           699:                        if (flags & X509v3_KU_KEY_CERT_SIGN)
        !           700:                        {
        !           701:                                /* we use the caBasicConstraint, MUST be set */
        !           702:                        }
        !           703:                }
        !           704:                ASN1_BIT_STRING_free(usage);
        !           705:                return TRUE;
        !           706:        }
        !           707:        return FALSE;
        !           708: }
        !           709: 
        !           710: /**
        !           711:  * Parse ExtendedKeyUsage
        !           712:  */
        !           713: static bool parse_extKeyUsage_ext(private_openssl_x509_t *this,
        !           714:                                                                  X509_EXTENSION *ext)
        !           715: {
        !           716:        EXTENDED_KEY_USAGE *usage;
        !           717:        int i;
        !           718: 
        !           719:        usage = X509V3_EXT_d2i(ext);
        !           720:        if (usage)
        !           721:        {
        !           722:                for (i = 0; i < sk_ASN1_OBJECT_num(usage); i++)
        !           723:                {
        !           724:                        switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(usage, i)))
        !           725:                        {
        !           726:                                case NID_server_auth:
        !           727:                                        this->flags |= X509_SERVER_AUTH;
        !           728:                                        break;
        !           729:                                case NID_client_auth:
        !           730:                                        this->flags |= X509_CLIENT_AUTH;
        !           731:                                        break;
        !           732:                                case NID_OCSP_sign:
        !           733:                                        this->flags |= X509_OCSP_SIGNER;
        !           734:                                        break;
        !           735:                                default:
        !           736:                                        break;
        !           737:                        }
        !           738:                }
        !           739:                sk_ASN1_OBJECT_pop_free(usage, ASN1_OBJECT_free);
        !           740:                return TRUE;
        !           741:        }
        !           742:        return FALSE;
        !           743: }
        !           744: 
        !           745: /**
        !           746:  * Parse CRL distribution points
        !           747:  */
        !           748: bool openssl_parse_crlDistributionPoints(X509_EXTENSION *ext,
        !           749:                                                                                 linked_list_t *list)
        !           750: {
        !           751:        CRL_DIST_POINTS *cdps;
        !           752:        DIST_POINT *cdp;
        !           753:        identification_t *id, *issuer;
        !           754:        x509_cdp_t *entry;
        !           755:        char *uri;
        !           756:        int i, j, k, point_num, name_num, issuer_num, len;
        !           757: 
        !           758:        cdps = X509V3_EXT_d2i(ext);
        !           759:        if (!cdps)
        !           760:        {
        !           761:                return FALSE;
        !           762:        }
        !           763:        point_num = sk_DIST_POINT_num(cdps);
        !           764:        for (i = 0; i < point_num; i++)
        !           765:        {
        !           766:                cdp = sk_DIST_POINT_value(cdps, i);
        !           767:                if (cdp)
        !           768:                {
        !           769:                        if (cdp->distpoint && cdp->distpoint->type == 0 &&
        !           770:                                cdp->distpoint->name.fullname)
        !           771:                        {
        !           772:                                name_num = sk_GENERAL_NAME_num(cdp->distpoint->name.fullname);
        !           773:                                for (j = 0; j < name_num; j++)
        !           774:                                {
        !           775:                                        id = general_name2id(sk_GENERAL_NAME_value(
        !           776:                                                                                        cdp->distpoint->name.fullname, j));
        !           777:                                        if (id)
        !           778:                                        {
        !           779:                                                len = asprintf(&uri, "%Y", id);
        !           780:                                                if (!len)
        !           781:                                                {
        !           782:                                                        free(uri);
        !           783:                                                }
        !           784:                                                else if (len > 0)
        !           785:                                                {
        !           786:                                                        if (cdp->CRLissuer)
        !           787:                                                        {
        !           788:                                                                issuer_num = sk_GENERAL_NAME_num(cdp->CRLissuer);
        !           789:                                                                for (k = 0; k < issuer_num; k++)
        !           790:                                                                {
        !           791:                                                                        issuer = general_name2id(
        !           792:                                                                                sk_GENERAL_NAME_value(cdp->CRLissuer, k));
        !           793:                                                                        if (issuer)
        !           794:                                                                        {
        !           795:                                                                                INIT(entry,
        !           796:                                                                                        .uri = strdup(uri),
        !           797:                                                                                        .issuer = issuer,
        !           798:                                                                                );
        !           799:                                                                                list->insert_last(list, entry);
        !           800:                                                                        }
        !           801:                                                                }
        !           802:                                                                free(uri);
        !           803:                                                        }
        !           804:                                                        else
        !           805:                                                        {
        !           806:                                                                INIT(entry,
        !           807:                                                                        .uri = uri,
        !           808:                                                                );
        !           809:                                                                list->insert_last(list, entry);
        !           810:                                                        }
        !           811:                                                }
        !           812:                                                id->destroy(id);
        !           813:                                        }
        !           814:                                }
        !           815:                        }
        !           816: 
        !           817:                        DIST_POINT_free(cdp);
        !           818:                }
        !           819:        }
        !           820:        sk_DIST_POINT_free(cdps);
        !           821:        return TRUE;
        !           822: }
        !           823: 
        !           824: /**
        !           825:  * Parse authorityInfoAccess with OCSP URIs
        !           826:  */
        !           827: static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this,
        !           828:                                                                                  X509_EXTENSION *ext)
        !           829: {
        !           830:        AUTHORITY_INFO_ACCESS *infos;
        !           831:        ACCESS_DESCRIPTION *desc;
        !           832:        identification_t *id;
        !           833:        int i, num, len;
        !           834:        char *uri;
        !           835: 
        !           836:        infos = X509V3_EXT_d2i(ext);
        !           837:        if (!infos)
        !           838:        {
        !           839:                return FALSE;
        !           840:        }
        !           841:        num = sk_ACCESS_DESCRIPTION_num(infos);
        !           842:        for (i = 0; i < num; i++)
        !           843:        {
        !           844:                desc = sk_ACCESS_DESCRIPTION_value(infos, i);
        !           845:                if (desc)
        !           846:                {
        !           847:                        if (openssl_asn1_known_oid(desc->method) == OID_OCSP)
        !           848:                        {
        !           849:                                id = general_name2id(desc->location);
        !           850:                                if (id)
        !           851:                                {
        !           852:                                        len = asprintf(&uri, "%Y", id);
        !           853:                                        if (!len)
        !           854:                                        {
        !           855:                                                free(uri);
        !           856:                                        }
        !           857:                                        else if (len > 0)
        !           858:                                        {
        !           859:                                                this->ocsp_uris->insert_last(this->ocsp_uris, uri);
        !           860:                                        }
        !           861:                                        id->destroy(id);
        !           862:                                }
        !           863:                        }
        !           864:                        ACCESS_DESCRIPTION_free(desc);
        !           865:                }
        !           866:        }
        !           867:        sk_ACCESS_DESCRIPTION_free(infos);
        !           868:        return TRUE;
        !           869: }
        !           870: 
        !           871: #ifndef OPENSSL_NO_RFC3779
        !           872: 
        !           873: /**
        !           874:  * Parse a single block of ipAddrBlock extension
        !           875:  */
        !           876: static void parse_ipAddrBlock_ext_fam(private_openssl_x509_t *this,
        !           877:                                                                          IPAddressFamily *fam)
        !           878: {
        !           879:        const IPAddressOrRanges *list;
        !           880:        IPAddressOrRange *aor;
        !           881:        traffic_selector_t *ts;
        !           882:        ts_type_t type;
        !           883:        chunk_t from, to;
        !           884:        int i, afi;
        !           885: 
        !           886:        if (fam->ipAddressChoice->type != IPAddressChoice_addressesOrRanges)
        !           887:        {
        !           888:                return;
        !           889:        }
        !           890: 
        !           891:        afi = X509v3_addr_get_afi(fam);
        !           892:        switch (afi)
        !           893:        {
        !           894:                case IANA_AFI_IPV4:
        !           895:                        from = chunk_alloca(4);
        !           896:                        to = chunk_alloca(4);
        !           897:                        type = TS_IPV4_ADDR_RANGE;
        !           898:                        break;
        !           899:                case IANA_AFI_IPV6:
        !           900:                        from = chunk_alloca(16);
        !           901:                        to = chunk_alloca(16);
        !           902:                        type = TS_IPV6_ADDR_RANGE;
        !           903:                        break;
        !           904:                default:
        !           905:                        return;
        !           906:        }
        !           907: 
        !           908:        list = fam->ipAddressChoice->u.addressesOrRanges;
        !           909:        for (i = 0; i < sk_IPAddressOrRange_num(list); i++)
        !           910:        {
        !           911:                aor = sk_IPAddressOrRange_value(list, i);
        !           912:                if (X509v3_addr_get_range(aor, afi, from.ptr, to.ptr, from.len) > 0)
        !           913:                {
        !           914:                        ts = traffic_selector_create_from_bytes(0, type, from, 0, to, 65535);
        !           915:                        if (ts)
        !           916:                        {
        !           917:                                this->ipAddrBlocks->insert_last(this->ipAddrBlocks, ts);
        !           918:                        }
        !           919:                }
        !           920:        }
        !           921: }
        !           922: 
        !           923: /**
        !           924:  * Parse ipAddrBlock extension
        !           925:  */
        !           926: static bool parse_ipAddrBlock_ext(private_openssl_x509_t *this,
        !           927:                                                                  X509_EXTENSION *ext)
        !           928: {
        !           929:        STACK_OF(IPAddressFamily) *blocks;
        !           930:        IPAddressFamily *fam;
        !           931: 
        !           932:        blocks = (STACK_OF(IPAddressFamily)*)X509V3_EXT_d2i(ext);
        !           933:        if (!blocks)
        !           934:        {
        !           935:                return FALSE;
        !           936:        }
        !           937: 
        !           938:        if (!X509v3_addr_is_canonical(blocks))
        !           939:        {
        !           940:                sk_IPAddressFamily_free(blocks);
        !           941:                return FALSE;
        !           942:        }
        !           943: 
        !           944:        while (sk_IPAddressFamily_num(blocks) > 0)
        !           945:        {
        !           946:                fam = sk_IPAddressFamily_pop(blocks);
        !           947:                parse_ipAddrBlock_ext_fam(this, fam);
        !           948:                IPAddressFamily_free(fam);
        !           949:        }
        !           950:        sk_IPAddressFamily_free(blocks);
        !           951: 
        !           952:        this->flags |= X509_IP_ADDR_BLOCKS;
        !           953:        return TRUE;
        !           954: }
        !           955: #endif /* !OPENSSL_NO_RFC3779 */
        !           956: 
        !           957: /**
        !           958:  * Parse authorityKeyIdentifier extension
        !           959:  */
        !           960: static bool parse_authKeyIdentifier_ext(private_openssl_x509_t *this,
        !           961:                                                                                X509_EXTENSION *ext)
        !           962: {
        !           963:        AUTHORITY_KEYID *keyid;
        !           964: 
        !           965:        keyid = (AUTHORITY_KEYID*)X509V3_EXT_d2i(ext);
        !           966:        if (keyid)
        !           967:        {
        !           968:                free(this->authKeyIdentifier.ptr);
        !           969:                this->authKeyIdentifier = chunk_clone(
        !           970:                                                                                openssl_asn1_str2chunk(keyid->keyid));
        !           971:                AUTHORITY_KEYID_free(keyid);
        !           972:                return TRUE;
        !           973:        }
        !           974:        return FALSE;
        !           975: }
        !           976: 
        !           977: /**
        !           978:  * Parse subjectKeyIdentifier extension
        !           979:  */
        !           980: static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t *this,
        !           981:                                                                                   X509_EXTENSION *ext)
        !           982: {
        !           983:        chunk_t ostr;
        !           984: 
        !           985:        ostr = openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext));
        !           986:        /* quick and dirty unwrap of octet string */
        !           987:        if (ostr.len > 2 &&
        !           988:                ostr.ptr[0] == V_ASN1_OCTET_STRING && ostr.ptr[1] == ostr.len - 2)
        !           989:        {
        !           990:                free(this->subjectKeyIdentifier.ptr);
        !           991:                this->subjectKeyIdentifier = chunk_clone(chunk_skip(ostr, 2));
        !           992:                return TRUE;
        !           993:        }
        !           994:        return FALSE;
        !           995: }
        !           996: 
        !           997: /**
        !           998:  * Parse X509 extensions we are interested in
        !           999:  */
        !          1000: static bool parse_extensions(private_openssl_x509_t *this)
        !          1001: {
        !          1002:        const STACK_OF(X509_EXTENSION) *extensions;
        !          1003:        int i, num;
        !          1004: 
        !          1005:        /* unless we see a keyUsage extension we are compliant with RFC 4945 */
        !          1006:        this->flags |= X509_IKE_COMPLIANT;
        !          1007: 
        !          1008:        extensions = X509_get0_extensions(this->x509);
        !          1009:        if (extensions)
        !          1010:        {
        !          1011:                num = sk_X509_EXTENSION_num(extensions);
        !          1012: 
        !          1013:                for (i = 0; i < num; i++)
        !          1014:                {
        !          1015:                        X509_EXTENSION *ext;
        !          1016:                        bool ok;
        !          1017: 
        !          1018:                        ext = sk_X509_EXTENSION_value(extensions, i);
        !          1019:                        switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext)))
        !          1020:                        {
        !          1021:                                case NID_info_access:
        !          1022:                                        ok = parse_authorityInfoAccess_ext(this, ext);
        !          1023:                                        break;
        !          1024:                                case NID_authority_key_identifier:
        !          1025:                                        ok = parse_authKeyIdentifier_ext(this, ext);
        !          1026:                                        break;
        !          1027:                                case NID_subject_key_identifier:
        !          1028:                                        ok = parse_subjectKeyIdentifier_ext(this, ext);
        !          1029:                                        break;
        !          1030:                                case NID_subject_alt_name:
        !          1031:                                        ok = parse_generalNames_ext(this->subjectAltNames, ext);
        !          1032:                                        break;
        !          1033:                                case NID_issuer_alt_name:
        !          1034:                                        ok = parse_generalNames_ext(this->issuerAltNames, ext);
        !          1035:                                        break;
        !          1036:                                case NID_basic_constraints:
        !          1037:                                        ok = parse_basicConstraints_ext(this, ext);
        !          1038:                                        break;
        !          1039:                                case NID_key_usage:
        !          1040:                                        ok = parse_keyUsage_ext(this, ext);
        !          1041:                                        break;
        !          1042:                                case NID_ext_key_usage:
        !          1043:                                        ok = parse_extKeyUsage_ext(this, ext);
        !          1044:                                        break;
        !          1045:                                case NID_crl_distribution_points:
        !          1046:                                        ok = openssl_parse_crlDistributionPoints(ext, this->crl_uris);
        !          1047:                                        break;
        !          1048: #ifndef OPENSSL_NO_RFC3779
        !          1049:                                case NID_sbgp_ipAddrBlock:
        !          1050:                                        ok = parse_ipAddrBlock_ext(this, ext);
        !          1051:                                        break;
        !          1052: #endif /* !OPENSSL_NO_RFC3779 */
        !          1053:                                default:
        !          1054:                                        ok = X509_EXTENSION_get_critical(ext) == 0 ||
        !          1055:                                                 !lib->settings->get_bool(lib->settings,
        !          1056:                                                                        "%s.x509.enforce_critical", TRUE, lib->ns);
        !          1057:                                        if (!ok)
        !          1058:                                        {
        !          1059:                                                char buf[80] = "";
        !          1060: 
        !          1061:                                                OBJ_obj2txt(buf, sizeof(buf),
        !          1062:                                                                        X509_EXTENSION_get_object(ext), 0);
        !          1063:                                                DBG1(DBG_LIB, "found unsupported critical X.509 "
        !          1064:                                                         "extension: %s", buf);
        !          1065:                                        }
        !          1066:                                        break;
        !          1067:                        }
        !          1068:                        if (!ok)
        !          1069:                        {
        !          1070:                                return FALSE;
        !          1071:                        }
        !          1072:                }
        !          1073:        }
        !          1074:        return TRUE;
        !          1075: }
        !          1076: 
        !          1077: /**
        !          1078:  * Parse a DER encoded x509 certificate
        !          1079:  */
        !          1080: static bool parse_certificate(private_openssl_x509_t *this)
        !          1081: {
        !          1082:        const unsigned char *ptr = this->encoding.ptr;
        !          1083:        hasher_t *hasher;
        !          1084:        chunk_t chunk, sig_scheme, sig_scheme_tbs;
        !          1085:        ASN1_OBJECT *oid;
        !          1086: #if OPENSSL_VERSION_NUMBER >= 0x10100000L
        !          1087:        const X509_ALGOR *alg;
        !          1088: #else
        !          1089:        X509_ALGOR *alg;
        !          1090: #endif
        !          1091:        key_type_t ed_type = KEY_ED448;
        !          1092: 
        !          1093:        this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
        !          1094:        if (!this->x509)
        !          1095:        {
        !          1096:                return FALSE;
        !          1097:        }
        !          1098:        if (X509_get_version(this->x509) < 0 || X509_get_version(this->x509) > 2)
        !          1099:        {
        !          1100:                DBG1(DBG_LIB, "unsupported x509 version: %d",
        !          1101:                         X509_get_version(this->x509) + 1);
        !          1102:                return FALSE;
        !          1103:        }
        !          1104: 
        !          1105:        this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509));
        !          1106:        this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509));
        !          1107: 
        !          1108:        if (!X509_PUBKEY_get0_param(&oid, NULL, NULL, NULL,
        !          1109:                                                            X509_get_X509_PUBKEY(this->x509)))
        !          1110:        {
        !          1111:                return FALSE;
        !          1112:        }
        !          1113:        switch (openssl_asn1_known_oid(oid))
        !          1114:        {
        !          1115:                case OID_RSASSA_PSS:
        !          1116:                        /* TODO: we should treat such keys special and use the params as
        !          1117:                         * restrictions regarding the use of this key (or rather the
        !          1118:                         * associated private key) */
        !          1119:                case OID_RSA_ENCRYPTION:
        !          1120:                        this->pubkey = lib->creds->create(lib->creds,
        !          1121:                                        CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_ASN1_DER,
        !          1122:                                        openssl_asn1_str2chunk(X509_get0_pubkey_bitstr(this->x509)),
        !          1123:                                        BUILD_END);
        !          1124:                        break;
        !          1125:                case OID_EC_PUBLICKEY:
        !          1126:                        /* for ECDSA, we need the full subjectPublicKeyInfo, as it contains
        !          1127:                         * the curve parameters. */
        !          1128:                        chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
        !          1129:                        this->pubkey = lib->creds->create(lib->creds,
        !          1130:                                        CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER,
        !          1131:                                        chunk, BUILD_END);
        !          1132:                        free(chunk.ptr);
        !          1133:                        break;
        !          1134:                case OID_ED25519:
        !          1135:                        ed_type = KEY_ED25519;
        !          1136:                        /* fall-through */
        !          1137:                case OID_ED448:
        !          1138:                        /* for EdDSA, the parsers expect the full subjectPublicKeyInfo */
        !          1139:                        chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
        !          1140:                        this->pubkey = lib->creds->create(lib->creds,
        !          1141:                                        CRED_PUBLIC_KEY, ed_type, BUILD_BLOB_ASN1_DER,
        !          1142:                                        chunk, BUILD_END);
        !          1143:                        free(chunk.ptr);
        !          1144:                        break;
        !          1145:                default:
        !          1146:                        DBG1(DBG_LIB, "unsupported public key algorithm");
        !          1147:                        break;
        !          1148:        }
        !          1149:        if (!this->subject || !this->issuer || !this->pubkey)
        !          1150:        {
        !          1151:                return FALSE;
        !          1152:        }
        !          1153: 
        !          1154:        this->notBefore = openssl_asn1_to_time(X509_get0_notBefore(this->x509));
        !          1155:        this->notAfter = openssl_asn1_to_time(X509_get0_notAfter(this->x509));
        !          1156: 
        !          1157:        /* while X509_ALGOR_cmp() is declared in the headers of older OpenSSL
        !          1158:         * versions, at least on Ubuntu 14.04 it is not actually defined */
        !          1159:        X509_get0_signature(NULL, &alg, this->x509);
        !          1160:        sig_scheme = openssl_i2chunk(X509_ALGOR, (X509_ALGOR*)alg);
        !          1161:        alg = X509_get0_tbs_sigalg(this->x509);
        !          1162:        sig_scheme_tbs = openssl_i2chunk(X509_ALGOR, (X509_ALGOR*)alg);
        !          1163:        if (!chunk_equals(sig_scheme, sig_scheme_tbs))
        !          1164:        {
        !          1165:                free(sig_scheme_tbs.ptr);
        !          1166:                free(sig_scheme.ptr);
        !          1167:                return FALSE;
        !          1168:        }
        !          1169:        free(sig_scheme_tbs.ptr);
        !          1170: 
        !          1171:        INIT(this->scheme);
        !          1172:        if (!signature_params_parse(sig_scheme, 0, this->scheme))
        !          1173:        {
        !          1174:                DBG1(DBG_ASN, "unable to parse signature algorithm");
        !          1175:                free(sig_scheme.ptr);
        !          1176:                return FALSE;
        !          1177:        }
        !          1178:        free(sig_scheme.ptr);
        !          1179: 
        !          1180:        if (!parse_extensions(this))
        !          1181:        {
        !          1182:                return FALSE;
        !          1183:        }
        !          1184: 
        !          1185:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
        !          1186:        if (!hasher || !hasher->allocate_hash(hasher, this->encoding, &this->hash))
        !          1187:        {
        !          1188:                DESTROY_IF(hasher);
        !          1189:                return FALSE;
        !          1190:        }
        !          1191:        hasher->destroy(hasher);
        !          1192: 
        !          1193:        if (issued_by(this, &this->public.x509.interface, NULL))
        !          1194:        {
        !          1195:                this->flags |= X509_SELF_SIGNED;
        !          1196:        }
        !          1197:        return TRUE;
        !          1198: }
        !          1199: 
        !          1200: openssl_x509_t *openssl_x509_load(certificate_type_t type, va_list args)
        !          1201: {
        !          1202:        chunk_t blob = chunk_empty;
        !          1203:        x509_flag_t flags = 0;
        !          1204: 
        !          1205:        while (TRUE)
        !          1206:        {
        !          1207:                switch (va_arg(args, builder_part_t))
        !          1208:                {
        !          1209:                        case BUILD_BLOB_ASN1_DER:
        !          1210:                                blob = va_arg(args, chunk_t);
        !          1211:                                continue;
        !          1212:                        case BUILD_X509_FLAG:
        !          1213:                                flags |= va_arg(args, x509_flag_t);
        !          1214:                                continue;
        !          1215:                        case BUILD_END:
        !          1216:                                break;
        !          1217:                        default:
        !          1218:                                return NULL;
        !          1219:                }
        !          1220:                break;
        !          1221:        }
        !          1222: 
        !          1223:        if (blob.ptr)
        !          1224:        {
        !          1225:                private_openssl_x509_t *this;
        !          1226: 
        !          1227:                this = create_empty();
        !          1228:                this->encoding = chunk_clone(blob);
        !          1229:                this->flags |= flags;
        !          1230:                if (parse_certificate(this))
        !          1231:                {
        !          1232:                        return &this->public;
        !          1233:                }
        !          1234:                DBG1(DBG_LIB, "OpenSSL X.509 parsing failed");
        !          1235:                destroy(this);
        !          1236:        }
        !          1237:        return NULL;
        !          1238: }

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