2011-01-19 13:48:47 +00:00
|
|
|
/*
|
2014-01-19 01:09:44 +00:00
|
|
|
* This file Copyright (C) 2007-2014 Mnemosyne LLC
|
2007-09-20 16:32:01 +00:00
|
|
|
*
|
2014-01-21 03:10:30 +00:00
|
|
|
* It may be used under the GNU GPL versions 2 or 3
|
2014-01-19 01:09:44 +00:00
|
|
|
* or any future license endorsed by Mnemosyne LLC.
|
2007-09-20 16:32:01 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2007-11-09 20:07:52 +00:00
|
|
|
#include <assert.h>
|
2014-12-04 20:45:18 +00:00
|
|
|
#include <string.h> /* memcpy (), memmove (), memset () */
|
2007-10-25 13:59:46 +00:00
|
|
|
|
2010-04-23 16:36:16 +00:00
|
|
|
#include "transmission.h"
|
2007-09-20 16:32:01 +00:00
|
|
|
#include "crypto.h"
|
2014-12-04 11:27:38 +00:00
|
|
|
#include "crypto-utils.h"
|
2007-09-20 16:32:01 +00:00
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
***
|
|
|
|
**/
|
|
|
|
|
|
|
|
#define PRIME_LEN 96
|
2009-12-12 03:51:36 +00:00
|
|
|
#define DH_PRIVKEY_LEN 20
|
|
|
|
|
2007-09-20 16:32:01 +00:00
|
|
|
static const uint8_t dh_P[PRIME_LEN] =
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
|
|
|
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
|
|
|
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
|
|
|
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
|
|
|
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
|
|
|
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
|
|
|
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
|
|
|
0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63,
|
2007-09-20 16:32:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const uint8_t dh_G[] = { 2 };
|
|
|
|
|
2007-10-13 23:15:43 +00:00
|
|
|
/**
|
|
|
|
***
|
|
|
|
**/
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static void ensureKeyExists(tr_crypto* crypto)
|
2007-10-11 02:22:17 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
if (crypto->dh == NULL)
|
2007-10-11 02:22:17 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
size_t public_key_length;
|
#4400, #5462: Move DH helpers to crypto-utils
On a way to factoring out OpenSSL support to a standalone file to ease
addition of other crypto libraries support in the future, move helpers
providing DH key exchange to crypto-utils.{c,h}. OpenSSL-related
functionality (DH context management) is moved to crypto-utils-openssl.c.
Since we know in advance that DH secret key management code will be the
same for most of backends, implement common functionality in separate
crypto-utils-fallback.c.
Add new tr_dh_ctx_t and tr_dh_secret_t types and functions to be
implemented by crypto backends:
* tr_dh_new - allocate DH context,
* tr_dh_free - free the context,
* tr_dh_make_key - generate private/public keypair,
* tr_dh_agree - perform DH key exchange and generate secret key,
* tr_dh_secret_derive - calculate secret key hash,
* tr_dh_secret_free - free the secret key,
* tr_dh_align_key - align some DH key in the buffer allocated for it.
Make DH secret key not accessible in plain form outside the crypto
backend. This allows for implementations where the key is managed by
the underlying library and is not even exposed to our backend.
2014-12-04 19:18:08 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
crypto->dh = tr_dh_new(dh_P, sizeof(dh_P), dh_G, sizeof(dh_G));
|
|
|
|
tr_dh_make_key(crypto->dh, DH_PRIVKEY_LEN, crypto->myPublicKey, &public_key_length);
|
#4400, #5462: Move DH helpers to crypto-utils
On a way to factoring out OpenSSL support to a standalone file to ease
addition of other crypto libraries support in the future, move helpers
providing DH key exchange to crypto-utils.{c,h}. OpenSSL-related
functionality (DH context management) is moved to crypto-utils-openssl.c.
Since we know in advance that DH secret key management code will be the
same for most of backends, implement common functionality in separate
crypto-utils-fallback.c.
Add new tr_dh_ctx_t and tr_dh_secret_t types and functions to be
implemented by crypto backends:
* tr_dh_new - allocate DH context,
* tr_dh_free - free the context,
* tr_dh_make_key - generate private/public keypair,
* tr_dh_agree - perform DH key exchange and generate secret key,
* tr_dh_secret_derive - calculate secret key hash,
* tr_dh_secret_free - free the secret key,
* tr_dh_align_key - align some DH key in the buffer allocated for it.
Make DH secret key not accessible in plain form outside the crypto
backend. This allows for implementations where the key is managed by
the underlying library and is not even exposed to our backend.
2014-12-04 19:18:08 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
assert(public_key_length == KEY_LEN);
|
2009-12-12 03:51:36 +00:00
|
|
|
}
|
2007-10-13 23:15:43 +00:00
|
|
|
}
|
2007-09-20 16:32:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_cryptoConstruct(tr_crypto* crypto, const uint8_t* torrentHash, bool isIncoming)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
memset(crypto, 0, sizeof(tr_crypto));
|
2007-09-20 16:32:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
crypto->isIncoming = isIncoming;
|
|
|
|
tr_cryptoSetTorrentHash(crypto, torrentHash);
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_cryptoDestruct(tr_crypto* crypto)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_dh_secret_free(crypto->mySecret);
|
|
|
|
tr_dh_free(crypto->dh);
|
|
|
|
tr_rc4_free(crypto->enc_key);
|
|
|
|
tr_rc4_free(crypto->dec_key);
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
***
|
|
|
|
**/
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
bool tr_cryptoComputeSecret(tr_crypto* crypto, const uint8_t* peerPublicKey)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
ensureKeyExists(crypto);
|
|
|
|
crypto->mySecret = tr_dh_agree(crypto->dh, peerPublicKey, KEY_LEN);
|
|
|
|
return crypto->mySecret != NULL;
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
const uint8_t* tr_cryptoGetMyPublicKey(const tr_crypto* crypto, int* setme_len)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
ensureKeyExists((tr_crypto*)crypto);
|
|
|
|
*setme_len = KEY_LEN;
|
|
|
|
return crypto->myPublicKey;
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
***
|
|
|
|
**/
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static void initRC4(tr_crypto* crypto, tr_rc4_ctx_t* setme, const char* key)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
uint8_t buf[SHA_DIGEST_LENGTH];
|
2007-09-20 16:32:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
assert(crypto->torrentHashIsSet);
|
2007-09-20 16:32:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (*setme == NULL)
|
|
|
|
{
|
|
|
|
*setme = tr_rc4_new();
|
|
|
|
}
|
2014-12-04 12:37:08 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (tr_cryptoSecretKeySha1(crypto, key, 4, crypto->torrentHash, SHA_DIGEST_LENGTH, buf))
|
|
|
|
{
|
|
|
|
tr_rc4_set_key(*setme, buf, SHA_DIGEST_LENGTH);
|
|
|
|
}
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_cryptoDecryptInit(tr_crypto* crypto)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
uint8_t discard[1024];
|
|
|
|
const char* txt = crypto->isIncoming ? "keyA" : "keyB";
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
initRC4(crypto, &crypto->dec_key, txt);
|
|
|
|
tr_rc4_process(crypto->dec_key, discard, discard, sizeof(discard));
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_cryptoDecrypt(tr_crypto* crypto, size_t buf_len, const void* buf_in, void* buf_out)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
/* FIXME: someone calls this function with uninitialized key */
|
|
|
|
if (crypto->dec_key == NULL)
|
2014-12-04 12:37:08 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
if (buf_in != buf_out)
|
|
|
|
{
|
|
|
|
memmove(buf_out, buf_in, buf_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2014-12-04 12:37:08 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_rc4_process(crypto->dec_key, buf_in, buf_out, buf_len);
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_cryptoEncryptInit(tr_crypto* crypto)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
uint8_t discard[1024];
|
|
|
|
const char* txt = crypto->isIncoming ? "keyB" : "keyA";
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
initRC4(crypto, &crypto->enc_key, txt);
|
|
|
|
tr_rc4_process(crypto->enc_key, discard, discard, sizeof(discard));
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_cryptoEncrypt(tr_crypto* crypto, size_t buf_len, const void* buf_in, void* buf_out)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
/* FIXME: someone calls this function with uninitialized key */
|
|
|
|
if (crypto->enc_key == NULL)
|
2014-12-04 12:37:08 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
if (buf_in != buf_out)
|
|
|
|
{
|
|
|
|
memmove(buf_out, buf_in, buf_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2014-12-04 12:37:08 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_rc4_process(crypto->enc_key, buf_in, buf_out, buf_len);
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
bool tr_cryptoSecretKeySha1(const tr_crypto* crypto, const void* prepend_data, size_t prepend_data_size,
|
|
|
|
const void* append_data, size_t append_data_size, uint8_t* hash)
|
#4400, #5462: Move DH helpers to crypto-utils
On a way to factoring out OpenSSL support to a standalone file to ease
addition of other crypto libraries support in the future, move helpers
providing DH key exchange to crypto-utils.{c,h}. OpenSSL-related
functionality (DH context management) is moved to crypto-utils-openssl.c.
Since we know in advance that DH secret key management code will be the
same for most of backends, implement common functionality in separate
crypto-utils-fallback.c.
Add new tr_dh_ctx_t and tr_dh_secret_t types and functions to be
implemented by crypto backends:
* tr_dh_new - allocate DH context,
* tr_dh_free - free the context,
* tr_dh_make_key - generate private/public keypair,
* tr_dh_agree - perform DH key exchange and generate secret key,
* tr_dh_secret_derive - calculate secret key hash,
* tr_dh_secret_free - free the secret key,
* tr_dh_align_key - align some DH key in the buffer allocated for it.
Make DH secret key not accessible in plain form outside the crypto
backend. This allows for implementations where the key is managed by
the underlying library and is not even exposed to our backend.
2014-12-04 19:18:08 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
assert(crypto != NULL);
|
|
|
|
assert(crypto->mySecret != NULL);
|
#4400, #5462: Move DH helpers to crypto-utils
On a way to factoring out OpenSSL support to a standalone file to ease
addition of other crypto libraries support in the future, move helpers
providing DH key exchange to crypto-utils.{c,h}. OpenSSL-related
functionality (DH context management) is moved to crypto-utils-openssl.c.
Since we know in advance that DH secret key management code will be the
same for most of backends, implement common functionality in separate
crypto-utils-fallback.c.
Add new tr_dh_ctx_t and tr_dh_secret_t types and functions to be
implemented by crypto backends:
* tr_dh_new - allocate DH context,
* tr_dh_free - free the context,
* tr_dh_make_key - generate private/public keypair,
* tr_dh_agree - perform DH key exchange and generate secret key,
* tr_dh_secret_derive - calculate secret key hash,
* tr_dh_secret_free - free the secret key,
* tr_dh_align_key - align some DH key in the buffer allocated for it.
Make DH secret key not accessible in plain form outside the crypto
backend. This allows for implementations where the key is managed by
the underlying library and is not even exposed to our backend.
2014-12-04 19:18:08 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
return tr_dh_secret_derive(crypto->mySecret, prepend_data, prepend_data_size, append_data, append_data_size, hash);
|
#4400, #5462: Move DH helpers to crypto-utils
On a way to factoring out OpenSSL support to a standalone file to ease
addition of other crypto libraries support in the future, move helpers
providing DH key exchange to crypto-utils.{c,h}. OpenSSL-related
functionality (DH context management) is moved to crypto-utils-openssl.c.
Since we know in advance that DH secret key management code will be the
same for most of backends, implement common functionality in separate
crypto-utils-fallback.c.
Add new tr_dh_ctx_t and tr_dh_secret_t types and functions to be
implemented by crypto backends:
* tr_dh_new - allocate DH context,
* tr_dh_free - free the context,
* tr_dh_make_key - generate private/public keypair,
* tr_dh_agree - perform DH key exchange and generate secret key,
* tr_dh_secret_derive - calculate secret key hash,
* tr_dh_secret_free - free the secret key,
* tr_dh_align_key - align some DH key in the buffer allocated for it.
Make DH secret key not accessible in plain form outside the crypto
backend. This allows for implementations where the key is managed by
the underlying library and is not even exposed to our backend.
2014-12-04 19:18:08 +00:00
|
|
|
}
|
|
|
|
|
2007-09-20 16:32:01 +00:00
|
|
|
/**
|
|
|
|
***
|
|
|
|
**/
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_cryptoSetTorrentHash(tr_crypto* crypto, const uint8_t* hash)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
crypto->torrentHashIsSet = hash != NULL;
|
2007-09-20 16:32:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (hash)
|
|
|
|
{
|
|
|
|
memcpy(crypto->torrentHash, hash, SHA_DIGEST_LENGTH);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memset(crypto->torrentHash, 0, SHA_DIGEST_LENGTH);
|
|
|
|
}
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
const uint8_t* tr_cryptoGetTorrentHash(const tr_crypto* crypto)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
assert(crypto);
|
2007-09-20 16:32:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
return crypto->torrentHashIsSet ? crypto->torrentHash : NULL;
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
bool tr_cryptoHasTorrentHash(const tr_crypto* crypto)
|
2007-09-20 16:32:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
assert(crypto);
|
2007-09-20 16:32:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
return crypto->torrentHashIsSet;
|
2007-09-20 16:32:01 +00:00
|
|
|
}
|