source: branches/encryption/libtransmission/handshake.c @ 2938

Last change on this file since 2938 was 2938, checked in by charles, 15 years ago

make things a little less prolix - s/tr_encryption/tr_crypto/

  • Property svn:keywords set to Date Rev Author Id
File size: 25.1 KB
Line 
1/*
2 * This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: handshake.c 2938 2007-08-29 12:24:34Z charles $
11 */
12
13#include <assert.h>
14#include <inttypes.h>
15#include <limits.h> /* UCHAR_MAX */
16#include <string.h>
17#include <arpa/inet.h>
18
19#include <openssl/bn.h>
20#include <openssl/dh.h>
21//#include <openssl/rc4.h>
22//#include <openssl/sha.h>
23
24#include <event.h>
25
26#include <libtransmission/transmission.h>
27#include <libtransmission/crypto.h>
28#include <libtransmission/handshake.h>
29#include <libtransmission/peer-connection.h>
30#include <libtransmission/utils.h>
31
32/***
33****
34***/
35
36#define HANDSHAKE_NAME          "\023BitTorrent protocol"
37#define HANDSHAKE_NAME_LEN      20
38#define HANDSHAKE_FLAGS_LEN     8
39#define HANDSHAKE_SIZE          68
40
41/* these macros test and set the bit indicating extended messaging support */
42#ifdef DISABLE_EXTMSGS
43#define HANDSHAKE_HAS_EXTMSGS( bits ) ( 0 )
44#define HANDSHAKE_SET_EXTMSGS( bits ) ( (void)0 )
45#else
46#define HANDSHAKE_HAS_EXTMSGS( bits ) ( (bits)[5] & 0x10 )
47#define HANDSHAKE_SET_EXTMSGS( bits ) ( (bits)[5] |= 0x10 )
48#endif
49
50/* these macros test and set the bit indicating azureus protocol support */
51#ifdef DISABLE_AZPROTO
52#define HANDSHAKE_HAS_AZPROTO( bits ) ( 0 )
53#define HANDSHAKE_SET_AZPROTO( bits ) ( (void)0 )
54#else
55#define HANDSHAKE_HAS_AZPROTO( bits ) ( (bits)[0] & 0x80 )
56#define HANDSHAKE_SET_AZPROTO( bits ) ( (bits)[0] |= 0x80 )
57#endif
58
59/* http://www.azureuswiki.com/index.php/Extension_negotiation_protocol
60   these macros are to be used if both extended messaging and the
61   azureus protocol is supported, they indicate which protocol is preferred */
62#define HANDSHAKE_GET_EXTPREF( reserved )      ( (reserved)[5] & 0x03 )
63#define HANDSHAKE_SET_EXTPREF( reserved, val ) ( (reserved)[5] |= 0x03 & (val) )
64#define HANDSHAKE_EXTPREF_LTEP_FORCE   ( 0x0 )
65#define HANDSHAKE_EXTPREF_LTEP_PREFER  ( 0x1 )
66#define HANDSHAKE_EXTPREF_AZMP_PREFER  ( 0x2 )
67#define HANDSHAKE_EXTPREF_AZMP_FORCE   ( 0x3 )
68
69extern const char* getPeerId( void ) ;
70
71
72#define KEY_LEN 96
73#define PRIME_LEN 96
74#define VC_LENGTH 8
75
76
77typedef struct tr_handshake
78{
79    tr_peerConnection * connection;
80    tr_crypto * crypto;
81    struct tr_handle * handle;
82    uint8_t myPublicKey[96];
83    uint8_t mySecret[96];
84    uint8_t state;
85    uint8_t encryptionPreference;
86    uint8_t * resync;
87    uint16_t PadC_len;
88    uint16_t PadD_len;
89    uint8_t pad_b_buf[512 + 8];
90    int     pad_b_len;
91    int ia_len;
92    int resync_len;
93    int pad_d_len;
94    int crypto_select;
95    DH * dh;
96    uint8_t myReq1[SHA_DIGEST_LENGTH];
97    handshakeDoneCB doneCB;
98    void * doneUserData;
99}
100tr_handshake;
101
102static void
103fireDoneCB( tr_handshake * handshake, int isConnected );
104
105/**
106***
107**/
108
109enum /*ccc*/
110{
111    /* incoming */
112    AWAITING_HANDSHAKE,
113    AWAITING_YA,
114    SENDING_YB,
115    AWAITING_PAD_A,
116    AWAITING_CRYPTO_PROVIDE,
117    AWAITING_PAD_C,
118    AWAITING_IA,
119
120    /* outgoing */
121    SENDING_YA,
122    AWAITING_YB,
123    SENDING_CRYPTO_PROVIDE,
124    AWAITING_VC,
125    AWAITING_CRYPTO_SELECT,
126    AWAITING_PAD_D,
127    //AWAITING_PLAINTEXT_RESPONSE,
128   
129    SENDING_PLAINTEXT_HANDSHAKE
130};
131
132/**
133***
134**/
135
136static const char* getStateName( short state )
137{
138    const char * str = "f00!";
139    switch( state ) {
140        case AWAITING_HANDSHAKE:      str = "awaiting handshake"; break;
141        case AWAITING_YA:             str = "awaiting ya"; break;
142        case SENDING_YB:              str = "sending yb"; break;
143        case AWAITING_PAD_A:          str = "awaiting pad a"; break;
144        case AWAITING_CRYPTO_PROVIDE: str = "awaiting crypto_provide"; break;
145        case AWAITING_PAD_C:          str = "awaiting pad c"; break;
146        case AWAITING_IA:             str = "awaiting ia"; break;
147        case SENDING_YA:              str = "sending ya"; break;
148        case AWAITING_YB:             str = "awaiting yb"; break;
149        case SENDING_CRYPTO_PROVIDE:  str = "sending crypto provide"; break;
150        case AWAITING_VC:             str = "awaiting vc"; break;
151        case AWAITING_CRYPTO_SELECT:  str = "awaiting crypto select"; break;
152        case AWAITING_PAD_D:          str = "awaiting pad d"; break;
153        case SENDING_PLAINTEXT_HANDSHAKE: str = "sending plaintext handshake"; break;
154    }
155    return str;
156}
157
158static void
159setState( tr_handshake * handshake, short state )
160{
161    fprintf( stderr, "setting handshake %p to state [%s]\n", handshake, getStateName(state) );
162    handshake->state = state;
163}
164
165static void
166setReadState( tr_handshake * handshake, int state )
167{
168    setState( handshake, state );
169    tr_peerConnectionSetIOMode( handshake->connection, EV_READ );
170}
171
172static void
173sendPublicKey( tr_handshake * handshake )
174{
175    int i;
176    int len;
177    const uint8_t * public_key;
178    struct evbuffer * outbuf = evbuffer_new( );
179    uint8_t pad[512];
180
181    /* add our public key (Ya) */
182    public_key = tr_cryptoGetMyPublicKey( handshake->crypto, &len );
183    assert( len == KEY_LEN );
184    assert( public_key != NULL );
185    evbuffer_add( outbuf, public_key, len );
186
187    /* add some bullshit padding */
188    len = tr_rand( 512 );
189    for( i=0; i<len; ++i )
190        pad[i] = tr_rand( UCHAR_MAX );
191    evbuffer_add( outbuf, pad, len );
192
193    /* send it */
194    setState( handshake, SENDING_YA );
195    tr_peerConnectionWriteBuf( handshake->connection, outbuf );
196
197    /* cleanup */
198    evbuffer_free( outbuf );
199}
200
201static void
202buildHandshakeMessage( tr_handshake * handshake, uint8_t * buf )
203{
204    uint8_t *walk = buf;
205    const uint8_t * torrentHash = tr_cryptoGetTorrentHash( handshake->crypto );
206
207    memcpy( walk, HANDSHAKE_NAME, HANDSHAKE_NAME_LEN );
208    walk += HANDSHAKE_NAME_LEN;
209    memset( walk, 0, HANDSHAKE_FLAGS_LEN );
210    HANDSHAKE_SET_EXTMSGS( walk );
211    HANDSHAKE_SET_AZPROTO( walk );
212    HANDSHAKE_SET_EXTPREF( walk, HANDSHAKE_EXTPREF_LTEP_PREFER );
213    walk += HANDSHAKE_FLAGS_LEN;
214    memcpy( walk, torrentHash, SHA_DIGEST_LENGTH );
215    walk += SHA_DIGEST_LENGTH;
216    memcpy( walk, getPeerId(), TR_ID_LEN );
217    walk += TR_ID_LEN;
218    assert( walk-buf == HANDSHAKE_SIZE );
219}
220
221static void
222sendPlaintextHandshake( tr_handshake * handshake )
223{
224    uint8_t buf[HANDSHAKE_SIZE];
225    buildHandshakeMessage( handshake, buf );
226    setState( handshake, SENDING_PLAINTEXT_HANDSHAKE );
227    tr_peerConnectionWrite( handshake->connection, buf, HANDSHAKE_SIZE );
228}
229
230static void
231sendHandshake( tr_handshake * handshake )
232{
233    if( ( handshake->encryptionPreference == HANDSHAKE_ENCRYPTION_PREFERRED ) ||
234        ( handshake->encryptionPreference == HANDSHAKE_ENCRYPTION_REQUIRED ) )
235    {
236        sendPublicKey( handshake );
237    }
238    else
239    {
240        sendPlaintextHandshake( handshake );
241    }
242}
243
244/**
245***
246**/
247
248static int
249readYa( tr_handshake * handshake, struct evbuffer  * inbuf )
250{
251    uint8_t ya[KEY_LEN];
252    uint8_t *walk, outbuf[KEY_LEN + 512];
253    const uint8_t *myKey, *secret;
254    int len;
255
256    if( EVBUFFER_LENGTH( inbuf ) < KEY_LEN )
257        return READ_MORE;
258
259    /* read the incoming peer's public key */
260    evbuffer_remove( inbuf, ya, KEY_LEN );
261    secret = tr_cryptoComputeSecret( handshake->crypto, ya );
262    memcpy( handshake->mySecret, secret, KEY_LEN );
263    tr_sha1( handshake->myReq1, "req1", 4, secret, KEY_LEN, NULL );
264
265    /* send our public key to the peer */
266    walk = outbuf;
267    myKey = tr_cryptoGetMyPublicKey( handshake->crypto, &len );
268    memcpy( walk, myKey, len );
269    len = tr_rand( 512 );
270    while( len-- )
271        *walk++ = tr_rand( UCHAR_MAX );
272    setState( handshake, SENDING_YB );
273    tr_peerConnectionWrite( handshake->connection, outbuf, walk-outbuf );
274
275    return READ_DONE;
276}
277
278static int
279readPadA( tr_handshake * handshake, struct evbuffer * inbuf )
280{
281    uint8_t * pch;
282
283    /**
284    *** Resynchronizing on HASH('req1',S)
285    **/
286
287    pch = memchr( EVBUFFER_DATA(inbuf),
288                  handshake->myReq1[0],
289                  EVBUFFER_LENGTH(inbuf) );
290    if( pch == NULL ) {
291        evbuffer_drain( inbuf, EVBUFFER_LENGTH(inbuf) );
292        return READ_MORE;
293    }
294    evbuffer_drain( inbuf, pch-EVBUFFER_DATA(inbuf) );
295    if( EVBUFFER_LENGTH(inbuf) < SHA_DIGEST_LENGTH )
296        return READ_MORE;
297    if( memcmp( EVBUFFER_DATA(inbuf), handshake->myReq1, SHA_DIGEST_LENGTH ) ) {
298        evbuffer_drain( inbuf, 1 );
299        return READ_AGAIN;
300    }
301
302    setState( handshake, AWAITING_CRYPTO_PROVIDE );
303    return READ_AGAIN;
304}
305
306static int
307readCryptoProvide( tr_handshake * handshake, struct evbuffer * inbuf )
308{
309    /* HASH('req2', SKEY) xor HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC)) */
310
311    int i;
312    uint8_t vc_in[VC_LENGTH];
313    uint8_t req2[SHA_DIGEST_LENGTH];
314    uint8_t req3[SHA_DIGEST_LENGTH];
315    uint8_t obfuscatedTorrentHash[SHA_DIGEST_LENGTH];
316    uint16_t padc_len = 0;
317    uint32_t crypto_provide = 0;
318    const size_t needlen = SHA_DIGEST_LENGTH + VC_LENGTH + sizeof(crypto_provide) + sizeof(padc_len);
319    tr_torrent * tor = NULL;
320
321    if( EVBUFFER_LENGTH(inbuf) < needlen )
322        return READ_MORE;
323
324    /* TODO: confirm they sent HASH('req1',S) here? */
325    evbuffer_drain( inbuf, SHA_DIGEST_LENGTH );
326
327    /* This next piece is HASH('req2', SKEY) xor HASH('req3', S) ...
328     * we can get the first half of that (the obufscatedTorrentHash)
329     * by building the latter and xor'ing it with what the peer sent us */
330    fprintf( stderr, "reading obfuscated torrent hash...\n" );
331    evbuffer_remove( inbuf, req2, SHA_DIGEST_LENGTH );
332    tr_sha1( req3, "req3", 4, handshake->mySecret, KEY_LEN, NULL );
333    for( i=0; i<SHA_DIGEST_LENGTH; ++i )
334        obfuscatedTorrentHash[i] = req2[i] ^ req3[i];
335    tor = tr_torrentFindFromObfuscatedHash( handshake->handle, obfuscatedTorrentHash );
336    assert( tor != NULL );
337    fprintf( stderr, "found the torrent; it's [%s]\n", tor->info.name );
338    tr_peerConnectionSetTorrent( handshake->connection, tor );
339
340    /* next part: ENCRYPT(VC, crypto_provide, len(PadC), */
341
342    tr_cryptoDecryptInit( handshake->crypto );
343
344    evbuffer_remove( inbuf, vc_in, VC_LENGTH );
345    tr_cryptoDecrypt( handshake->crypto, VC_LENGTH, vc_in, vc_in );
346    fprintf( stderr, "read vc -> %d %d %d %d %d %d %d %d\n",
347        (int)vc_in[0], (int)vc_in[1], (int)vc_in[2], (int)vc_in[3],
348        (int)vc_in[4], (int)vc_in[5], (int)vc_in[6], (int)vc_in[7] );
349
350    evbuffer_remove( inbuf, &crypto_provide, sizeof(crypto_provide) );
351    tr_cryptoDecrypt( handshake->crypto, sizeof(crypto_provide),
352                          &crypto_provide, &crypto_provide );
353    crypto_provide = ntohl( crypto_provide );
354    fprintf( stderr, "crypto_provide is %d\n", (int)crypto_provide );
355
356    evbuffer_remove( inbuf, &padc_len, sizeof(padc_len) );
357    tr_cryptoDecrypt( handshake->crypto, sizeof(padc_len), &padc_len, &padc_len );
358    padc_len = ntohs( padc_len );
359    fprintf( stderr, "padc is %d\n", (int)padc_len );
360    handshake->PadC_len = padc_len;
361    setState( handshake, AWAITING_PAD_C );
362    return READ_AGAIN;
363}
364
365static int
366readPadC( tr_handshake * handshake, struct evbuffer * inbuf )
367{
368    uint16_t ia_len;
369    const size_t needlen = handshake->PadC_len + sizeof(uint16_t);
370
371    if( EVBUFFER_LENGTH(inbuf) < needlen )
372        return READ_MORE;
373
374    evbuffer_drain( inbuf, needlen );
375
376    evbuffer_remove( inbuf, &ia_len, sizeof(ia_len) );
377    ia_len = ntohs( ia_len );
378    fprintf( stderr, "ia_len is %d\n", (int)ia_len );
379    handshake->ia_len = ia_len;
380    setState( handshake, AWAITING_IA );
381    return READ_AGAIN;
382}
383
384static int
385readIA( tr_handshake * handshake, struct evbuffer * inbuf )
386{
387    const size_t needlen = handshake->ia_len;
388    uint8_t * ia;
389
390    if( EVBUFFER_LENGTH(inbuf) < needlen )
391        return READ_MORE;
392
393    ia = tr_new( uint8_t, handshake->ia_len );
394    evbuffer_remove( inbuf, ia, handshake->ia_len );
395    tr_cryptoDecrypt( handshake->crypto, handshake->ia_len, ia, ia );
396    fprintf( stderr, "got their payload ia: [%*.*s]\n", (int)needlen, (int)needlen, ia );
397
398    handshake->state = -1;
399    abort( );
400}
401
402/**
403***
404**/
405
406static int
407readYb( tr_handshake * handshake, struct evbuffer * inbuf )
408{
409    int isEncrypted;
410    const uint8_t * secret;
411    const size_t needlen = KEY_LEN;
412    uint8_t yb[KEY_LEN];
413    struct evbuffer * outbuf;
414
415    if( EVBUFFER_LENGTH(inbuf) < needlen )
416        return READ_MORE;
417
418    isEncrypted = memcmp( EVBUFFER_DATA(inbuf), HANDSHAKE_NAME, HANDSHAKE_NAME_LEN );
419    fprintf( stderr, "got a %s handshake\n", (isEncrypted ? "encrypted" : "plaintext") );
420    if( !isEncrypted ) {
421        setState( handshake, AWAITING_HANDSHAKE );
422        return READ_AGAIN;
423    }
424
425    /* compute the secret */
426    evbuffer_remove( inbuf, yb, KEY_LEN );
427    secret = tr_cryptoComputeSecret( handshake->crypto, yb );
428    memcpy( handshake->mySecret, secret, KEY_LEN );
429
430    /* now send these: HASH('req1', S), HASH('req2', SKEY) xor HASH('req3', S),
431     * ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA) */
432    outbuf = evbuffer_new( );
433
434    /* HASH('req1', S) */
435    {
436        uint8_t req1[SHA_DIGEST_LENGTH];
437        tr_sha1( req1, "req1", 4, secret, KEY_LEN, NULL );
438        evbuffer_add( outbuf, req1, SHA_DIGEST_LENGTH );
439    }
440
441    /* HASH('req2', SKEY) xor HASH('req3', S) */
442    {
443        int i;
444        uint8_t req2[SHA_DIGEST_LENGTH];
445        uint8_t req3[SHA_DIGEST_LENGTH];
446        uint8_t buf[SHA_DIGEST_LENGTH];
447        tr_sha1( req2, "req2", 4, tr_cryptoGetTorrentHash(handshake->crypto), SHA_DIGEST_LENGTH, NULL );
448        tr_sha1( req3, "req3", 4, secret, KEY_LEN, NULL );
449        for( i=0; i<SHA_DIGEST_LENGTH; ++i )
450            buf[i] = req2[i] ^ req3[i];
451        evbuffer_add( outbuf, buf, SHA_DIGEST_LENGTH );
452    }
453     
454    /* ENCRYPT(VC, crypto_provide, len(PadC), PadC */
455    {
456        uint8_t vc[VC_LENGTH] = { 0, 0, 0, 0, 0, 0, 0, 0 };
457        uint8_t pad[512];
458        uint16_t i, len;
459        uint32_t crypto_provide;
460
461        tr_cryptoEncryptInit( handshake->crypto );
462       
463        /* vc */ 
464        tr_cryptoEncrypt( handshake->crypto, VC_LENGTH, vc, vc );
465        evbuffer_add( outbuf, vc, VC_LENGTH );
466
467        /* crypto_provide */
468        crypto_provide = 0;
469        if( handshake->encryptionPreference != HANDSHAKE_PLAINTEXT_REQUIRED )
470            crypto_provide |= (1<<0);
471        if( handshake->encryptionPreference != HANDSHAKE_ENCRYPTION_REQUIRED )
472            crypto_provide |= (1<<1);
473        assert( 1<=crypto_provide && crypto_provide<=3 );
474        crypto_provide = htonl( crypto_provide );
475        tr_cryptoEncrypt( handshake->crypto, sizeof(crypto_provide), &crypto_provide, &crypto_provide );
476fprintf( stderr, "crypto_provide is [%d]\n", crypto_provide );
477        evbuffer_add( outbuf, &crypto_provide, sizeof(crypto_provide) );
478
479        /* len(padc) */
480        i = len = tr_rand( 512 );
481        i = htons( i );
482        tr_cryptoEncrypt( handshake->crypto, sizeof(i), &i, &i );
483        evbuffer_add( outbuf, &i, sizeof(i) );
484
485        /* padc */
486        for( i=0; i<len; ++i ) pad[i] = tr_rand( UCHAR_MAX );
487        evbuffer_add( outbuf, pad, len );
488    }
489
490    /* ENCRYPT len(IA)), ENCRYPT(IA) */
491    {
492        uint16_t i;
493        uint8_t msg[HANDSHAKE_SIZE];
494        buildHandshakeMessage( handshake, msg );
495
496        i = htons( HANDSHAKE_SIZE );
497        tr_cryptoEncrypt( handshake->crypto, sizeof(uint16_t), &i, &i );
498        evbuffer_add( outbuf, &i, sizeof(uint16_t) );
499
500        tr_cryptoEncrypt( handshake->crypto, HANDSHAKE_SIZE, msg, msg );
501        evbuffer_add( outbuf, msg, HANDSHAKE_SIZE );
502    }
503
504    /* send it */
505    tr_cryptoDecryptInit( handshake->crypto );
506    setState( handshake, SENDING_CRYPTO_PROVIDE );
507    tr_peerConnectionWriteBuf( handshake->connection, outbuf );
508
509    /* cleanup */
510    evbuffer_free( outbuf );
511    return READ_DONE;
512}
513
514static int
515readVC( tr_handshake * handshake, struct evbuffer * inbuf )
516{
517    const uint8_t key[VC_LENGTH] = { 0, 0, 0, 0, 0, 0, 0, 0 };
518    const int key_len = VC_LENGTH;
519    uint8_t tmp[VC_LENGTH];
520
521    /* note: this works w/o having to `unwind' the buffer if
522     * we read too much, but it is pretty brute-force.
523     * it would be nice to make this cleaner. */
524    for( ;; )
525    {
526        if( EVBUFFER_LENGTH(inbuf) < VC_LENGTH )
527            return READ_MORE;
528
529        memcpy( tmp, EVBUFFER_DATA(inbuf), key_len );
530        tr_cryptoDecryptInit( handshake->crypto );
531        tr_cryptoDecrypt( handshake->crypto, key_len, tmp, tmp );
532        if( !memcmp( tmp, key, key_len ) )
533            break;
534
535        evbuffer_drain( inbuf, 1 );
536    }
537
538    evbuffer_drain( inbuf, key_len );
539    setState( handshake, AWAITING_CRYPTO_SELECT );
540    return READ_AGAIN;
541}
542
543//ccc
544static int
545readCryptoSelect( tr_handshake * handshake, struct evbuffer * inbuf )
546{
547    uint32_t crypto_select;
548    uint16_t pad_d_len;
549    const size_t needlen = sizeof(uint32_t) + sizeof(uint16_t);
550
551    if( EVBUFFER_LENGTH(inbuf) < needlen )
552        return READ_MORE;
553
554 //   tr_cryptoDecryptInit( handshake->crypto );
555
556    evbuffer_remove( inbuf, &crypto_select, sizeof(uint32_t) );
557    tr_cryptoDecrypt( handshake->crypto, sizeof(uint32_t), &crypto_select, &crypto_select );
558    fprintf( stderr, "crypto select 1 is %d\n", crypto_select );
559    crypto_select = ntohl( crypto_select );
560    handshake->crypto_select = crypto_select;
561    assert( crypto_select==1 || crypto_select==2 );
562    fprintf( stderr, "crypto select 2 is %d\n", crypto_select );
563
564    evbuffer_remove( inbuf, &pad_d_len, sizeof(uint16_t) );
565    tr_cryptoDecrypt( handshake->crypto, sizeof(uint16_t), &pad_d_len, &pad_d_len );
566    pad_d_len = ntohs( pad_d_len );
567    fprintf( stderr, "pad_d_len is %d\n", (int)pad_d_len );
568    assert( pad_d_len <= 512 );
569    handshake->pad_d_len = pad_d_len;
570
571    setState( handshake, AWAITING_PAD_D );
572    return READ_AGAIN;
573}
574
575static int
576readPadD( tr_handshake * handshake, struct evbuffer * inbuf )
577{
578    const size_t needlen = handshake->pad_d_len;
579    uint8_t * buf;
580
581fprintf( stderr, "pad d: need %d, got %d\n", (int)needlen, (int)EVBUFFER_LENGTH(inbuf) );
582    if( EVBUFFER_LENGTH(inbuf) < needlen )
583        return READ_MORE;
584
585    buf = tr_new( uint8_t, needlen );
586    evbuffer_remove( inbuf, buf, needlen );
587    tr_cryptoDecrypt( handshake->crypto, needlen, buf, buf );
588    tr_free( buf );
589
590    setState( handshake, AWAITING_HANDSHAKE );
591    return READ_AGAIN;
592}
593
594/*ccc*/
595static int
596readHandshake( tr_handshake * handshake, struct evbuffer * inbuf )
597{
598    int i;
599    int ltep = 0;
600    int azmp = 0;
601    int encrypted;
602    uint8_t pstrlen;
603    uint8_t * pstr;
604    uint8_t reserved[8];
605    uint8_t hash[SHA_DIGEST_LENGTH];
606    uint8_t peer_id[20];
607
608fprintf( stderr, "handshake payload: need %d, got %d\n", (int)HANDSHAKE_SIZE, (int)EVBUFFER_LENGTH(inbuf) );
609
610    if( EVBUFFER_LENGTH(inbuf) < HANDSHAKE_SIZE )
611        return READ_MORE;
612
613    /* pstrlen */
614    evbuffer_remove( inbuf, &pstrlen, 1 );
615    fprintf( stderr, "pstrlen 1 is %d [%c]\n", (int)pstrlen, pstrlen );
616    encrypted = pstrlen != 19;
617    if( encrypted ) {
618        fprintf( stderr, "clearly it's encrypted...\n" );
619        //tr_cryptoDecryptInit( handshake->crypto );
620        tr_cryptoDecrypt( handshake->crypto, 1, &pstrlen, &pstrlen );
621    }
622    fprintf( stderr, "pstrlen is %d [%c]\n", (int)pstrlen, pstrlen );
623    //assert( pstrlen == 19 );
624
625    /* pstr (BitTorrent) */
626    pstr = tr_new( uint8_t, pstrlen+1 );
627    evbuffer_remove( inbuf, pstr, pstrlen );
628    if( encrypted )
629        tr_cryptoDecrypt( handshake->crypto, pstrlen, pstr, pstr );
630    pstr[pstrlen] = '\0';
631    fprintf( stderr, "pstrlen is [%s]\n", pstr );
632    assert( !strcmp( (char*)pstr, "BitTorrent protocol" ) );
633
634    /* reserved bytes */
635    evbuffer_remove( inbuf, reserved, sizeof(reserved) );
636    if( encrypted )
637        tr_cryptoDecrypt( handshake->crypto, sizeof(reserved), reserved, reserved );
638
639    /* torrent hash */
640    evbuffer_remove( inbuf, hash, sizeof(hash) );
641    if( encrypted )
642        tr_cryptoDecrypt( handshake->crypto, sizeof(hash), hash, hash );
643    assert( !memcmp( hash, tr_peerConnectionGetTorrent(handshake->connection)->info.hash, SHA_DIGEST_LENGTH ) );
644
645
646    /* peer id */
647    evbuffer_remove( inbuf, peer_id, sizeof(peer_id) );
648    if( encrypted )
649        tr_cryptoDecrypt( handshake->crypto, sizeof(peer_id), peer_id, peer_id );
650    fprintf( stderr, "peer_id: " );
651    for( i=0; i<20; ++i ) fprintf( stderr, "[%c]", peer_id[i] );
652    fprintf( stderr, "\n" );
653    tr_peerConnectionSetPeersId( handshake->connection, peer_id );
654
655    /**
656    ***
657    **/
658
659    ltep = HANDSHAKE_HAS_EXTMSGS( reserved ) ? 1 : 0;
660    azmp = HANDSHAKE_HAS_AZPROTO( reserved ) ? 1 : 0;
661    if( ltep && azmp ) {
662        switch( HANDSHAKE_GET_EXTPREF( reserved ) ) {
663            case HANDSHAKE_EXTPREF_LTEP_FORCE:
664            case HANDSHAKE_EXTPREF_LTEP_PREFER:
665                azmp = 0;
666                break;
667            case HANDSHAKE_EXTPREF_AZMP_FORCE:
668            case HANDSHAKE_EXTPREF_AZMP_PREFER:
669                ltep = 0;
670                break;
671        }
672    }
673    assert( !ltep || !azmp );
674         if( ltep ) { i = LT_EXTENSIONS_LTEP; fprintf(stderr,"using ltep\n" ); }
675    else if( azmp ) { i = LT_EXTENSIONS_AZMP; fprintf(stderr,"using azmp\n" ); }
676    else            { i = LT_EXTENSIONS_NONE; fprintf(stderr,"using no extensions\n" ); }
677    tr_peerConnectionSetExtension( handshake->connection, i );
678
679
680    if( !tr_peerConnectionIsIncoming( handshake->connection ) && ( i != LT_EXTENSIONS_AZMP ) ) {
681        fireDoneCB( handshake, TRUE );
682        return READ_DONE;
683    }
684
685   
686    assert( 0 && "FIXME" );
687    return 0;
688}
689
690/**
691***
692**/
693
694static ReadState
695canRead( struct bufferevent * evin, void * arg )
696{
697    tr_handshake * handshake = (tr_handshake *) arg;
698    struct evbuffer * inbuf = EVBUFFER_INPUT ( evin );
699    ReadState ret;
700    fprintf( stderr, "handling canRead; state is [%s]\n", getStateName(handshake->state) );
701
702    switch( handshake->state )
703    {
704        case AWAITING_HANDSHAKE:       ret = readHandshake    ( handshake, inbuf ); break;
705        case AWAITING_YA:              ret = readYa           ( handshake, inbuf ); break;
706        case AWAITING_PAD_A:           ret = readPadA         ( handshake, inbuf ); break;
707        case AWAITING_CRYPTO_PROVIDE:  ret = readCryptoProvide( handshake, inbuf ); break;
708        case AWAITING_PAD_C:           ret = readPadC         ( handshake, inbuf ); break;
709        case AWAITING_IA:              ret = readIA           ( handshake, inbuf ); break;
710
711        case AWAITING_YB:              ret = readYb           ( handshake, inbuf ); break;
712        case AWAITING_VC:              ret = readVC           ( handshake, inbuf ); break;
713        case AWAITING_CRYPTO_SELECT:   ret = readCryptoSelect ( handshake, inbuf ); break;
714        case AWAITING_PAD_D:           ret = readPadD         ( handshake, inbuf ); break;
715
716        default: assert( 0 );
717    }
718
719    return ret;
720}
721
722static void
723didWrite( struct bufferevent * evin UNUSED, void * arg )
724{
725    tr_handshake * handshake = (tr_handshake *) arg;
726    int state = -1;
727
728fprintf( stderr, "handshake %p got a didWrite event\n", handshake );
729
730    switch( handshake->state )
731    {
732        case SENDING_YA:                   state = AWAITING_YB; break;
733        case SENDING_YB:                   state = AWAITING_PAD_A; break;
734        case SENDING_CRYPTO_PROVIDE:       state = AWAITING_VC; break;
735    }
736
737    assert( state != -1 );
738    setState( handshake, state );
739    tr_peerConnectionReadOrWait( handshake->connection );
740}
741
742static void
743tr_handshakeFree( tr_handshake * handshake )
744{
745    /* FIXME */
746    tr_free( handshake );
747}
748
749static void
750fireDoneCB( tr_handshake * handshake, int isConnected )
751{
752    (*handshake->doneCB)(handshake->connection, isConnected, handshake->doneUserData);
753    tr_handshakeFree( handshake );
754}
755
756static void
757gotError( struct bufferevent * evbuf UNUSED, short what UNUSED, void * arg )
758{
759    tr_handshake * handshake = (tr_handshake *) arg;
760
761
762    /* if the error happened while we were sending a public key, we might
763     * have encountered a peer that doesn't do encryption... reconnect and
764     * try a plaintext handshake */
765    if(    ( handshake->state == SENDING_YA )
766        && ( handshake->encryptionPreference != HANDSHAKE_ENCRYPTION_REQUIRED )
767        && ( !tr_peerConnectionReconnect( handshake->connection ) ) )
768    {
769        handshake->encryptionPreference = HANDSHAKE_PLAINTEXT_REQUIRED;
770        sendPlaintextHandshake( handshake );
771    }
772    else fireDoneCB( handshake, FALSE );
773}
774
775/**
776***
777**/
778
779static tr_handshake*
780tr_handshakeNew( tr_peerConnection  * connection,
781                 int                  encryptionPreference,
782                 handshakeDoneCB      doneCB,
783                 void               * doneUserData )
784{
785    tr_handshake * handshake;
786
787static int count = 0;
788if( count++ ) return NULL;
789
790    handshake = tr_new0( tr_handshake, 1 );
791    handshake->connection = connection;
792    handshake->crypto = tr_peerConnectionGetCrypto( connection );
793    handshake->encryptionPreference = encryptionPreference;
794    handshake->doneCB = doneCB;
795    handshake->doneUserData = doneUserData;
796
797    tr_peerConnectionSetIOFuncs( connection, canRead, didWrite, gotError, handshake );
798
799    if( tr_peerConnectionIsIncoming( connection ) )
800    {
801        setReadState( handshake, AWAITING_HANDSHAKE );
802    }
803    else
804    {
805        sendHandshake( handshake );
806    }
807
808    return handshake;
809}
810
811void
812tr_handshakeAdd( struct tr_peerConnection * connection,
813                 int                        encryptionPreference,
814                 handshakeDoneCB            doneCB,   
815                 void                     * doneUserData )
816{
817    tr_handshakeNew( connection, encryptionPreference, doneCB, doneUserData );
818}
Note: See TracBrowser for help on using the repository browser.