Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2011 Martin Willi
        !             3:  * Copyright (C) 2011 revosec AG
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "pubkey_v1_authenticator.h"
        !            17: 
        !            18: #include <daemon.h>
        !            19: #include <sa/ikev1/keymat_v1.h>
        !            20: #include <encoding/payloads/hash_payload.h>
        !            21: #include <credentials/certificates/x509.h>
        !            22: 
        !            23: typedef struct private_pubkey_v1_authenticator_t private_pubkey_v1_authenticator_t;
        !            24: 
        !            25: /**
        !            26:  * Private data of an pubkey_v1_authenticator_t object.
        !            27:  */
        !            28: struct private_pubkey_v1_authenticator_t {
        !            29: 
        !            30:        /**
        !            31:         * Public authenticator_t interface.
        !            32:         */
        !            33:        pubkey_v1_authenticator_t public;
        !            34: 
        !            35:        /**
        !            36:         * Assigned IKE_SA
        !            37:         */
        !            38:        ike_sa_t *ike_sa;
        !            39: 
        !            40:        /**
        !            41:         * TRUE if we are initiator
        !            42:         */
        !            43:        bool initiator;
        !            44: 
        !            45:        /**
        !            46:         * DH key exchange
        !            47:         */
        !            48:        diffie_hellman_t *dh;
        !            49: 
        !            50:        /**
        !            51:         * Others DH public value
        !            52:         */
        !            53:        chunk_t dh_value;
        !            54: 
        !            55:        /**
        !            56:         * Encoded SA payload, without fixed header
        !            57:         */
        !            58:        chunk_t sa_payload;
        !            59: 
        !            60:        /**
        !            61:         * Encoded ID payload, without fixed header
        !            62:         */
        !            63:        chunk_t id_payload;
        !            64: 
        !            65:        /**
        !            66:         * Key type to use
        !            67:         */
        !            68:        key_type_t type;
        !            69: };
        !            70: 
        !            71: METHOD(authenticator_t, build, status_t,
        !            72:        private_pubkey_v1_authenticator_t *this, message_t *message)
        !            73: {
        !            74:        hash_payload_t *sig_payload;
        !            75:        chunk_t hash, sig, dh;
        !            76:        keymat_v1_t *keymat;
        !            77:        status_t status;
        !            78:        private_key_t *private;
        !            79:        identification_t *id;
        !            80:        auth_cfg_t *auth;
        !            81:        signature_scheme_t scheme = SIGN_RSA_EMSA_PKCS1_NULL;
        !            82: 
        !            83:        if (this->type == KEY_ECDSA)
        !            84:        {
        !            85:                scheme = SIGN_ECDSA_WITH_NULL;
        !            86:        }
        !            87: 
        !            88:        id = this->ike_sa->get_my_id(this->ike_sa);
        !            89:        auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
        !            90:        private = lib->credmgr->get_private(lib->credmgr, this->type, id, auth);
        !            91:        if (!private)
        !            92:        {
        !            93:                DBG1(DBG_IKE, "no %N private key found for '%Y'",
        !            94:                         key_type_names, this->type, id);
        !            95:                return NOT_FOUND;
        !            96:        }
        !            97: 
        !            98:        if (!this->dh->get_my_public_value(this->dh, &dh))
        !            99:        {
        !           100:                private->destroy(private);
        !           101:                return FAILED;
        !           102:        }
        !           103:        keymat = (keymat_v1_t*)this->ike_sa->get_keymat(this->ike_sa);
        !           104:        if (!keymat->get_hash(keymat, this->initiator, dh, this->dh_value,
        !           105:                                        this->ike_sa->get_id(this->ike_sa), this->sa_payload,
        !           106:                                        this->id_payload, &hash, &scheme))
        !           107:        {
        !           108:                private->destroy(private);
        !           109:                free(dh.ptr);
        !           110:                return FAILED;
        !           111:        }
        !           112:        free(dh.ptr);
        !           113: 
        !           114:        if (private->sign(private, scheme, NULL, hash, &sig))
        !           115:        {
        !           116:                sig_payload = hash_payload_create(PLV1_SIGNATURE);
        !           117:                sig_payload->set_hash(sig_payload, sig);
        !           118:                free(sig.ptr);
        !           119:                message->add_payload(message, &sig_payload->payload_interface);
        !           120:                status = SUCCESS;
        !           121:                DBG1(DBG_IKE, "authentication of '%Y' (myself) successful", id);
        !           122:        }
        !           123:        else
        !           124:        {
        !           125:                DBG1(DBG_IKE, "authentication of '%Y' (myself) failed", id);
        !           126:                status = FAILED;
        !           127:        }
        !           128:        private->destroy(private);
        !           129:        free(hash.ptr);
        !           130: 
        !           131:        return status;
        !           132: }
        !           133: 
        !           134: /**
        !           135:  * Check if the end-entity certificate, if any, is compliant with RFC 4945
        !           136:  */
        !           137: static bool is_compliant_cert(auth_cfg_t *auth)
        !           138: {
        !           139:        certificate_t *cert;
        !           140:        x509_t *x509;
        !           141: 
        !           142:        cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
        !           143:        if (!cert || cert->get_type(cert) != CERT_X509)
        !           144:        {
        !           145:                return TRUE;
        !           146:        }
        !           147:        x509 = (x509_t*)cert;
        !           148:        if (x509->get_flags(x509) & X509_IKE_COMPLIANT)
        !           149:        {
        !           150:                return TRUE;
        !           151:        }
        !           152:        DBG1(DBG_IKE, "rejecting certificate without digitalSignature or "
        !           153:                 "nonRepudiation keyUsage flags");
        !           154:        return FALSE;
        !           155: }
        !           156: 
        !           157: METHOD(authenticator_t, process, status_t,
        !           158:        private_pubkey_v1_authenticator_t *this, message_t *message)
        !           159: {
        !           160:        chunk_t hash, sig, dh;
        !           161:        keymat_v1_t *keymat;
        !           162:        public_key_t *public;
        !           163:        hash_payload_t *sig_payload;
        !           164:        auth_cfg_t *auth, *current_auth;
        !           165:        enumerator_t *enumerator;
        !           166:        status_t status = NOT_FOUND;
        !           167:        identification_t *id;
        !           168:        signature_scheme_t scheme = SIGN_RSA_EMSA_PKCS1_NULL;
        !           169: 
        !           170:        if (this->type == KEY_ECDSA)
        !           171:        {
        !           172:                scheme = SIGN_ECDSA_WITH_NULL;
        !           173:        }
        !           174: 
        !           175:        sig_payload = (hash_payload_t*)message->get_payload(message, PLV1_SIGNATURE);
        !           176:        if (!sig_payload)
        !           177:        {
        !           178:                DBG1(DBG_IKE, "SIG payload missing in message");
        !           179:                return FAILED;
        !           180:        }
        !           181: 
        !           182:        id = this->ike_sa->get_other_id(this->ike_sa);
        !           183:        if (!this->dh->get_my_public_value(this->dh, &dh))
        !           184:        {
        !           185:                return FAILED;
        !           186:        }
        !           187:        keymat = (keymat_v1_t*)this->ike_sa->get_keymat(this->ike_sa);
        !           188:        if (!keymat->get_hash(keymat, !this->initiator, this->dh_value, dh,
        !           189:                                        this->ike_sa->get_id(this->ike_sa), this->sa_payload,
        !           190:                                        this->id_payload, &hash, &scheme))
        !           191:        {
        !           192:                free(dh.ptr);
        !           193:                return FAILED;
        !           194:        }
        !           195:        free(dh.ptr);
        !           196: 
        !           197:        sig = sig_payload->get_hash(sig_payload);
        !           198:        auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
        !           199:        enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, this->type,
        !           200:                                                                                                                id, auth, TRUE);
        !           201:        while (enumerator->enumerate(enumerator, &public, &current_auth))
        !           202:        {
        !           203:                if (public->verify(public, scheme, NULL, hash, sig) &&
        !           204:                        is_compliant_cert(current_auth))
        !           205:                {
        !           206:                        DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
        !           207:                                 id, signature_scheme_names, scheme);
        !           208:                        status = SUCCESS;
        !           209:                        auth->merge(auth, current_auth, FALSE);
        !           210:                        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
        !           211:                        break;
        !           212:                }
        !           213:                else
        !           214:                {
        !           215:                        DBG1(DBG_IKE, "signature validation failed, looking for another key");
        !           216:                        status = FAILED;
        !           217:                }
        !           218:        }
        !           219:        enumerator->destroy(enumerator);
        !           220:        free(hash.ptr);
        !           221:        if (status != SUCCESS)
        !           222:        {
        !           223:                DBG1(DBG_IKE, "no trusted %N public key found for '%Y'",
        !           224:                         key_type_names, this->type, id);
        !           225:        }
        !           226:        return status;
        !           227: }
        !           228: 
        !           229: METHOD(authenticator_t, destroy, void,
        !           230:        private_pubkey_v1_authenticator_t *this)
        !           231: {
        !           232:        chunk_free(&this->id_payload);
        !           233:        free(this);
        !           234: }
        !           235: 
        !           236: /*
        !           237:  * Described in header.
        !           238:  */
        !           239: pubkey_v1_authenticator_t *pubkey_v1_authenticator_create(ike_sa_t *ike_sa,
        !           240:                                                                                bool initiator, diffie_hellman_t *dh,
        !           241:                                                                                chunk_t dh_value, chunk_t sa_payload,
        !           242:                                                                                chunk_t id_payload, key_type_t type)
        !           243: {
        !           244:        private_pubkey_v1_authenticator_t *this;
        !           245: 
        !           246:        INIT(this,
        !           247:                .public = {
        !           248:                        .authenticator = {
        !           249:                                .build = _build,
        !           250:                                .process = _process,
        !           251:                                .is_mutual = (void*)return_false,
        !           252:                                .destroy = _destroy,
        !           253:                        },
        !           254:                },
        !           255:                .ike_sa = ike_sa,
        !           256:                .initiator = initiator,
        !           257:                .dh = dh,
        !           258:                .dh_value = dh_value,
        !           259:                .sa_payload = sa_payload,
        !           260:                .id_payload = id_payload,
        !           261:                .type = type,
        !           262:        );
        !           263: 
        !           264:        return &this->public;
        !           265: }

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