Put the HMAC keys into the HMAC object instead on having them
[silc.git] / apps / silc / protocol.c
1 /*
2
3   protocol.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /*
21  * Client side of the protocols.
22  */
23 /*
24  * $Id$
25  * $Log$
26  * Revision 1.6  2000/07/14 06:12:29  priikone
27  *      Put the HMAC keys into the HMAC object instead on having them
28  *      saved elsewhere; we can use now silc_hmac_make instead of
29  *      silc_hmac_make_with_key.
30  *
31  * Revision 1.5  2000/07/07 11:36:09  priikone
32  *      Inform user when received unsupported public key from server.
33  *
34  * Revision 1.4  2000/07/07 06:53:45  priikone
35  *      Added support for server public key verification.
36  *
37  * Revision 1.3  2000/07/06 07:14:16  priikone
38  *      Deprecated old `channel_auth' protocol.
39  *
40  * Revision 1.2  2000/07/05 06:12:05  priikone
41  *      Global cosmetic changes.
42  *
43  * Revision 1.1.1.1  2000/06/27 11:36:56  priikone
44  *      Imported from internal CVS/Added Log headers.
45  *
46  *
47  */
48
49 #include "clientincludes.h"
50
51 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth);
52 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange);
53
54 /* SILC client protocol list */
55 const SilcProtocolObject silc_protocol_list[] =
56 {
57   { SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
58     silc_client_protocol_connection_auth },
59   { SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
60     silc_client_protocol_key_exchange },
61
62   { SILC_PROTOCOL_CLIENT_NONE, NULL },
63 };
64
65 /*
66  * Key Exhange protocol functions
67  */
68
69 /* Function that is called when SKE protocol sends packets to network. */
70
71 static void silc_client_protocol_ke_send_packet(SilcSKE ske,
72                                                 SilcBuffer packet,
73                                                 SilcPacketType type,
74                                                 void *context)
75 {
76   SilcProtocol protocol = (SilcProtocol)context;
77   SilcClientKEInternalContext *ctx = 
78     (SilcClientKEInternalContext *)protocol->context;
79   SilcClient client = (SilcClient)ctx->client;
80
81   /* Send the packet immediately */
82   silc_client_packet_send(client, ske->sock, type, NULL, 0, NULL, NULL,
83                           packet->data, packet->len, TRUE);
84
85 }
86
87 /* Callback that is called when we have received KE2 payload from
88    responder. We try to verify the public key now. */
89
90 static SilcSKEStatus 
91 silc_client_protocol_ke_verify_key(SilcSKE ske,
92                                    unsigned char *pk_data,
93                                    unsigned int pk_len,
94                                    SilcSKEPKType pk_type,
95                                    void *context)
96 {
97   SilcProtocol protocol = (SilcProtocol)context;
98   SilcClientKEInternalContext *ctx = 
99     (SilcClientKEInternalContext *)protocol->context;
100   SilcClient client = (SilcClient)ctx->client;
101
102   SILC_LOG_DEBUG(("Start"));
103
104   if (!silc_client_verify_server_key(client, ctx->sock, 
105                                      pk_data, pk_len, pk_type))
106     return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
107
108   return SILC_SKE_STATUS_OK;
109 }
110
111 /* Sets the negotiated key material into use for particular connection. */
112
113 static void silc_client_protocol_ke_set_keys(SilcSKE ske,
114                                              SilcSocketConnection sock,
115                                              SilcSKEKeyMaterial *keymat,
116                                              SilcCipher cipher,
117                                              SilcPKCS pkcs,
118                                              SilcHash hash)
119 {
120   SilcClientWindow win = (SilcClientWindow)sock->user_data;
121   SilcHash nhash;
122
123   SILC_LOG_DEBUG(("Setting new keys into use"));
124
125   /* Allocate cipher to be used in the communication */
126   silc_cipher_alloc(cipher->cipher->name, &win->send_key);
127   silc_cipher_alloc(cipher->cipher->name, &win->receive_key);
128
129   win->send_key->cipher->set_key(win->send_key->context, 
130                                  keymat->send_enc_key, 
131                                  keymat->enc_key_len);
132   win->send_key->set_iv(win->send_key, keymat->send_iv);
133   win->receive_key->cipher->set_key(win->receive_key->context, 
134                                     keymat->receive_enc_key, 
135                                     keymat->enc_key_len);
136   win->receive_key->set_iv(win->receive_key, keymat->receive_iv);
137
138   /* Allocate PKCS to be used */
139 #if 0
140   /* XXX Do we ever need to allocate PKCS for the connection??
141      If yes, we need to change KE protocol to get the initiators
142      public key. */
143   silc_pkcs_alloc(pkcs->pkcs->name, &win->public_Key);
144   silc_pkcs_set_public_key(win->public_key, ske->ke2_payload->pk_data, 
145                            ske->ke2_payload->pk_len);
146 #endif
147
148   /* Save HMAC key to be used in the communication. */
149   silc_hash_alloc(hash->hash->name, &nhash);
150   silc_hmac_alloc(nhash, &win->hmac);
151   silc_hmac_set_key(win->hmac, keymat->hmac_key, keymat->hmac_key_len);
152 }
153
154 /* Performs key exchange protocol. This is used for both initiator
155    and responder key exchange. This may be called recursively. */
156
157 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
158 {
159   SilcProtocol protocol = (SilcProtocol)context;
160   SilcClientKEInternalContext *ctx = 
161     (SilcClientKEInternalContext *)protocol->context;
162   SilcClient client = (SilcClient)ctx->client;
163   SilcSKEStatus status;
164
165   SILC_LOG_DEBUG(("Start"));
166
167   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
168     protocol->state = SILC_PROTOCOL_STATE_START;
169
170   switch(protocol->state) {
171   case SILC_PROTOCOL_STATE_START:
172     {
173       /*
174        * Start Protocol
175        */
176       SilcSKE ske;
177
178       /* Allocate Key Exchange object */
179       ske = silc_ske_alloc();
180       ctx->ske = ske;
181       
182       if (ctx->responder == TRUE) {
183 #if 0
184         SilcBuffer start_payload;
185
186
187         /* Start the key exchange by processing the received security
188            properties packet from initiator. */
189         status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
190                                           start_payload,
191                                           silc_client_protocol_ke_send_packet,
192                                           context);
193 #endif
194       } else {
195         SilcSKEStartPayload *start_payload;
196
197         /* Assemble security properties. */
198         silc_ske_assemble_security_properties(ske, &start_payload);
199
200         /* Start the key exchange by sending our security properties
201            to the remote end. */
202         status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
203                                           start_payload,
204                                           silc_client_protocol_ke_send_packet,
205                                           context);
206       }
207
208       if (status != SILC_SKE_STATUS_OK) {
209         switch(status) {
210           
211         default:
212           break;
213         }
214       }
215
216       /* Advance the state of the protocol. */
217       protocol->state++;
218     }
219     break;
220   case 2:
221     {
222       /* 
223        * Phase 1 
224        */
225       if (ctx->responder == TRUE) {
226 #if 0
227         status = 
228           silc_ske_responder_phase_1(ctx->ske, 
229                                      ctx->ske->start_payload,
230                                      silc_server_protocol_ke_send_packet,
231                                      context);
232 #endif
233       } else {
234         /* Call Phase-1 function. This processes the Key Exchange Start
235            paylaod reply we just got from the responder. The callback
236            function will receive the processed payload where we will
237            save it. */
238         status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet, NULL, NULL);
239       }
240
241       switch(status) {
242       default:
243         break;
244       }
245
246       /* Advance the state of the protocol and call the next state. */
247       protocol->state++;
248       protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
249     }
250     break;
251   case 3:
252     {
253       /* 
254        * Phase 2 
255        */
256       if (ctx->responder == TRUE) {
257 #if 0
258         status = 
259           silc_ske_responder_phase_2(ctx->ske, 
260                                      ctx->ske->start_payload,
261                                      silc_server_protocol_ke_send_packet,
262                                      context);
263 #endif
264       } else {
265         /* Call the Phase-2 function. This creates Diffie Hellman
266            key exchange parameters and sends our public part inside
267            Key Exhange 1 Payload to the responder. */
268         status = 
269           silc_ske_initiator_phase_2(ctx->ske,
270                                      silc_client_protocol_ke_send_packet,
271                                      context);
272       }
273
274       switch(status) {
275       default:
276         break;
277       }
278
279       /* Advance the state of the protocol. */
280       protocol->state++;
281     }
282     break;
283   case 4:
284     {
285       /* 
286        * Finish protocol
287        */
288       if (ctx->responder == TRUE) {
289         status = 0;
290 #if 0
291         status = 
292           silc_ske_responder_phase_2(ctx->ske, 
293                                      ctx->ske->start_payload,
294                                      silc_server_protocol_ke_send_packet,
295                                      context);
296 #endif
297       } else {
298         /* Finish the protocol. This verifies the Key Exchange 2 payload
299            sent by responder. */
300         status = silc_ske_initiator_finish(ctx->ske, ctx->packet,
301                                            silc_client_protocol_ke_verify_key,
302                                            context, NULL, NULL);
303       }
304
305       if (status != SILC_SKE_STATUS_OK) {
306
307         if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
308           silc_say(client, "Received unsupported server %s public key",
309                    ctx->sock->hostname);
310         } else {
311           silc_say(client, "Error during key exchange protocol with server %s",
312                    ctx->sock->hostname);
313         }
314         protocol->state = SILC_PROTOCOL_STATE_ERROR;
315         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
316         return;
317       }
318       
319       /* Send Ok to the other end. We will end the protocol as server
320          sends Ok to us when we will take the new keys into use. */
321       silc_ske_end(ctx->ske, silc_client_protocol_ke_send_packet, context);
322       
323       /* End the protocol on the next round */
324       protocol->state = SILC_PROTOCOL_STATE_END;
325     }
326     break;
327   case SILC_PROTOCOL_STATE_END:
328     {
329       /* 
330        * End protocol
331        */
332       SilcSKEKeyMaterial *keymat;
333
334       /* Process the key material */
335       keymat = silc_calloc(1, sizeof(*keymat));
336       silc_ske_process_key_material(ctx->ske, 16, (16 * 8), 16, keymat);
337
338       /* Take the negotiated keys into use. */
339       silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, keymat,
340                                        ctx->ske->prop->cipher,
341                                        ctx->ske->prop->pkcs,
342                                        ctx->ske->prop->hash);
343
344       /* Protocol has ended, call the final callback */
345       if (protocol->final_callback)
346         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
347       else
348         silc_protocol_free(protocol);
349     }
350     break;
351   case SILC_PROTOCOL_STATE_ERROR:
352     
353     /* On error the final callback is always called. */
354     if (protocol->final_callback)
355       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
356     else
357       silc_protocol_free(protocol);
358     break;
359   case SILC_PROTOCOL_STATE_UNKNOWN:
360     break;
361   }
362 }
363
364 /*
365  * Connection Authentication protocol functions
366  */
367
368 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
369 {
370   SilcProtocol protocol = (SilcProtocol)context;
371   SilcClientConnAuthInternalContext *ctx = 
372     (SilcClientConnAuthInternalContext *)protocol->context;
373   SilcClient client = (SilcClient)ctx->client;
374
375   SILC_LOG_DEBUG(("Start"));
376
377   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
378     protocol->state = SILC_PROTOCOL_STATE_START;
379
380   switch(protocol->state) {
381   case SILC_PROTOCOL_STATE_START:
382     {
383       /* 
384        * Start protocol. We send authentication data to the server
385        * to be authenticated.
386        */
387       SilcBuffer packet;
388       int payload_len = 0;
389       unsigned char *auth_data = NULL;
390       unsigned int auth_data_len = 0;
391
392       switch(ctx->auth_meth) {
393       case SILC_PROTOCOL_CONN_AUTH_NONE:
394         /* No authentication required */
395         break;
396
397       case SILC_PROTOCOL_CONN_AUTH_PASSWORD:
398         /* Password authentication */
399         if (ctx->auth_data && ctx->auth_data_len) {
400           auth_data = ctx->auth_data;
401           auth_data_len = ctx->auth_data_len;
402           break;
403         }
404
405         silc_say(client, "Password authentication required by server %s",
406                  ctx->sock->hostname);
407         auth_data = silc_client_ask_passphrase(client);
408         auth_data_len = strlen(auth_data);
409         break;
410
411       case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY:
412         /* XXX */
413         break;
414       }
415
416       payload_len = 4 + auth_data_len;
417       packet = silc_buffer_alloc(payload_len);
418       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
419       silc_buffer_format(packet,
420                          SILC_STR_UI_SHORT(payload_len),
421                          SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
422                          SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
423                          SILC_STR_END);
424
425       /* Send the packet to server */
426       silc_client_packet_send(client, ctx->sock,
427                               SILC_PACKET_CONNECTION_AUTH,
428                               NULL, 0, NULL, NULL,
429                               packet->data, packet->len, TRUE);
430
431       if (auth_data) {
432         memset(auth_data, 0, auth_data_len);
433         silc_free(auth_data);
434       }
435       silc_buffer_free(packet);
436       
437       /* Next state is end of protocol */
438       protocol->state = SILC_PROTOCOL_STATE_END;
439     }
440     break;
441
442   case SILC_PROTOCOL_STATE_END:
443     {
444       /* 
445        * End protocol. Nothing special to be done here.
446        */
447
448       /* Protocol has ended, call the final callback */
449       if (protocol->final_callback)
450         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
451       else
452         silc_protocol_free(protocol);
453     }
454     break;
455
456   case SILC_PROTOCOL_STATE_ERROR:
457     {
458       /* 
459        * Error
460        */
461
462       /* Error in protocol. Send FAILURE packet. Although I don't think
463          this could ever happen on client side. */
464       silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
465                               NULL, 0, NULL, NULL, NULL, 0, TRUE);
466
467       /* On error the final callback is always called. */
468       if (protocol->final_callback)
469         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
470       else
471         silc_protocol_free(protocol);
472     }
473     break;
474   case SILC_PROTOCOL_STATE_UNKNOWN:
475     break;
476   }
477 }
478