Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c, revision 1.1.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>