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, ¤t_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>