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