diff --git a/src/encrypt.c b/src/encrypt.c index 2e7f642e..417db3e0 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -3,8 +3,22 @@ #endif #include +#if defined(USE_CRYPTO_OPENSSL) #include #include +#elif defined(USE_CRYPTO_POLARSSL) +#include +#include +#include +#define CIPHER_UNSUPPORTED "unsupported" +#endif + +#include +#ifdef _WIN32 +#include +#else +#include +#endif #include "encrypt.h" #include "utils.h" @@ -13,12 +27,12 @@ static uint8_t *enc_table; static uint8_t *dec_table; -static uint8_t enc_key[EVP_MAX_KEY_LENGTH]; +static uint8_t enc_key[MAX_KEY_LENGTH]; static int enc_key_len; static int enc_iv_len; #ifdef DEBUG -static dump(char *tag, char *text) +static void dump(char *tag, char *text) { int i, len; len = strlen(text); @@ -49,6 +63,26 @@ static const char* supported_ciphers[CIPHER_NUM] = "seed-cfb" }; +#ifdef USE_CRYPTO_POLARSSL +static const char* supported_ciphers_polarssl[CIPHER_NUM] = +{ + "table", + "ARC4-128", + "AES-128-CFB128", + "AES-192-CFB128", + "AES-256-CFB128", + "BLOWFISH-CFB64", + "CAMELLIA-128-CFB128", + "CAMELLIA-192-CFB128", + "CAMELLIA-256-CFB128", + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED +}; +#endif + static int random_compare(const void *_x, const void *_y, uint32_t i, uint64_t a) { uint8_t x = *((uint8_t *) _x); @@ -135,6 +169,20 @@ int enc_get_iv_len() return enc_iv_len; } +unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md) +{ +#if defined(USE_CRYPTO_OPENSSL) + return MD5(d, n, md); +#elif defined(USE_CRYPTO_POLARSSL) + static unsigned char m[16]; + if (md == NULL) { + md = m; + } + md5(d, n, md); + return md; +#endif +} + void enc_table_init(const char *pass) { uint32_t i; @@ -145,7 +193,7 @@ void enc_table_init(const char *pass) enc_table = malloc(256); dec_table = malloc(256); - digest = MD5((const uint8_t *)pass, strlen(pass), NULL); + digest = enc_md5((const uint8_t *)pass, strlen(pass), NULL); for (i = 0; i < 8; i++) { @@ -168,57 +216,333 @@ void enc_table_init(const char *pass) } } -char* ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method) +int cipher_iv_size(const cipher_kt_t *cipher) { - if (method > TABLE) - { - const EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]); - if (cipher == NULL) - { - LOGE("Cipher %s not found in OpenSSL library", supported_ciphers[method]); - FATAL("Cannot initialize cipher"); +#if defined(USE_CRYPTO_OPENSSL) + return EVP_CIPHER_iv_length (cipher); +#elif defined(USE_CRYPTO_POLARSSL) + if (cipher == NULL) { + return 0; + } + return cipher->iv_size; +#endif +} + +int cipher_key_size (const cipher_kt_t *cipher) +{ +#if defined(USE_CRYPTO_OPENSSL) + return EVP_CIPHER_key_length(cipher); +#elif defined(USE_CRYPTO_POLARSSL) + if (cipher == NULL) { + return 0; + } + /* Override PolarSSL 32 bit default key size with sane 128 bit default */ + if (POLARSSL_CIPHER_ID_BLOWFISH == cipher->base->cipher) { + return 128 / 8; + } + return cipher->key_length / 8; +#endif +} + +int bytes_to_key(const cipher_kt_t *cipher, const digest_type_t *md, const uint8_t *pass, uint8_t *key, uint8_t *iv) +{ + size_t datal; + datal = strlen((const char *) pass); +#if defined(USE_CRYPTO_OPENSSL) + return EVP_BytesToKey(cipher, md, NULL, pass, datal, 1, key, iv); +#elif defined(USE_CRYPTO_POLARSSL) + md_context_t c; + unsigned char md_buf[MAX_MD_SIZE]; + int niv; + int nkey; + int addmd; + unsigned int mds; + unsigned int i; + int rv; + + nkey = cipher_key_size(cipher); + niv = cipher_iv_size(cipher); + rv = nkey; + if (pass == NULL) { + return nkey; + } + + memset(&c, 0, sizeof(md_context_t)); + if (md_init_ctx(&c, md)) { + return 0; + } + addmd = 0; + mds = md_get_size(md); + for (;;) { + int error; + do { + error = 1; + if (md_starts(&c)) { + break; + } + if (addmd) { + if (md_update(&c, &(md_buf[0]), mds)) { + break; + } + } else { + addmd = 1; + } + if (md_update(&c, pass, datal)) + break; + if (md_finish(&c, &(md_buf[0]))) + break; + error = 0; + } while (0); + if (error) { + md_free_ctx(&c); + memset(md_buf, 0, MAX_MD_SIZE); + return 0; } - EVP_CIPHER_CTX evp; - EVP_CIPHER_CTX_init(&evp); - if (!EVP_CipherInit_ex(&evp, cipher, NULL, NULL, NULL, 1)) - { - LOGE("Cannot initialize cipher %s", supported_ciphers[method]); - exit(EXIT_FAILURE); + + i=0; + if (nkey) { + for (;;) { + if (nkey == 0) break; + if (i == mds) break; + if (key != NULL) + *(key++)=md_buf[i]; + nkey--; + i++; + } } - if (!EVP_CIPHER_CTX_set_key_length(&evp, enc_key_len)) - { - EVP_CIPHER_CTX_cleanup(&evp); - LOGE("Invalid key length: %d", enc_key_len); - exit(EXIT_FAILURE); + if (niv && (i != mds)) { + for (;;) { + if (niv == 0) break; + if (i == mds) break; + if (iv != NULL) + *(iv++)=md_buf[i]; + niv--; + i++; + } } - if (method > RC4) - { - EVP_CIPHER_CTX_set_padding(&evp, 1); + if ((nkey == 0) && (niv == 0)) break; + } + md_free_ctx(&c); + memset(md_buf, 0, MAX_MD_SIZE); + return rv; +#endif +} + +int rand_bytes(uint8_t *output, int len) +{ +#if defined(USE_CRYPTO_OPENSSL) + return RAND_bytes(output, len); +#elif defined(USE_CRYPTO_POLARSSL) + static entropy_context ec = {0}; + static ctr_drbg_context cd_ctx = {0}; + static unsigned char rand_initialised = 0; + const size_t blen = min(len, CTR_DRBG_MAX_REQUEST); + + if (!rand_initialised) { +#ifdef _WIN32 + HCRYPTPROV hProvider; + union { + unsigned __int64 seed; + BYTE buffer[8]; + } rand_buffer; + + hProvider = 0; + if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, \ + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { + CryptGenRandom(hProvider, 8, rand_buffer.buffer); + CryptReleaseContext(hProvider, 0); + } else { + rand_buffer.seed = (unsigned __int64) clock(); + } +#else + FILE *urand; + union { + uint64_t seed; + uint8_t buffer[8]; + } rand_buffer; + + urand = fopen("/dev/urandom", "r"); + if (urand) { + fread(&rand_buffer.seed, sizeof(rand_buffer.seed), 1, urand); + fclose(urand); + } else { + rand_buffer.seed = (uint64_t) clock(); + } +#endif + entropy_init(&ec); + if (ctr_drbg_init(&cd_ctx, entropy_func, &ec, (const unsigned char *) rand_buffer.buffer, 8) != 0) { + entropy_free(&ec); + FATAL("Failed to initialize random generator"); } + rand_initialised = 1; + } +#ifdef DEBUG + int orig_len = len; + uint8_t *orig_output = output; +#endif + while (len > 0) { + if (ctr_drbg_random(&cd_ctx, output, blen) != 0) { + return 0; + } + output += blen; + len -= blen; + } + return 1; +#endif +} + +const cipher_kt_t *get_cipher_type(int method) +{ + if (method <= TABLE || method >= CIPHER_NUM) { + LOGE("get_cipher_type(): Illegal method"); + return NULL; + } + + const char *ciphername = supported_ciphers[method]; +#if defined(USE_CRYPTO_OPENSSL) + return EVP_get_cipherbyname(ciphername); +#elif defined(USE_CRYPTO_POLARSSL) + const char *polarname = supported_ciphers_polarssl[method]; + if (strcmp(polarname, CIPHER_UNSUPPORTED) == 0) { + LOGE("Cipher %s currently is not supported by PolarSSL library", ciphername); + FATAL("Unsupported cipher in PolarSSL"); + } + return cipher_info_from_string(polarname); +#endif +} + +const digest_type_t *get_digest_type(const char *digest) +{ + if (digest == NULL) { + LOGE("get_digest_type(): Digest name is null"); + return NULL; + } + +#if defined(USE_CRYPTO_OPENSSL) + return EVP_get_digestbyname(digest); +#elif defined(USE_CRYPTO_POLARSSL) + return md_info_from_string(digest); +#endif +} + +void cipher_context_init(cipher_ctx_t *evp, int method, int enc) +{ + if (method <= TABLE || method >= CIPHER_NUM) { + LOGE("cipher_context_init(): Illegal method"); + return; + } + + const char *ciphername = supported_ciphers[method]; + const cipher_kt_t *cipher = get_cipher_type(method); +#if defined(USE_CRYPTO_OPENSSL) + if (cipher == NULL) { + LOGE("Cipher %s not found in OpenSSL library", ciphername); + FATAL("Cannot initialize cipher"); + } + EVP_CIPHER_CTX_init(evp); + if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc)) { + LOGE("Cannot initialize cipher %s", ciphername); + exit(EXIT_FAILURE); + } + if (!EVP_CIPHER_CTX_set_key_length(evp, enc_key_len)) { + EVP_CIPHER_CTX_cleanup(evp); + LOGE("Invalid key length: %d", enc_key_len); + exit(EXIT_FAILURE); + } + if (method > RC4) { + EVP_CIPHER_CTX_set_padding(evp, 1); + } +#elif defined(USE_CRYPTO_POLARSSL) + if (cipher == NULL) { + LOGE("Cipher %s not found in PolarSSL library", ciphername); + FATAL("Cannot initialize PolarSSL cipher"); + } + if (cipher_init_ctx(evp, cipher) != 0) { + FATAL("Cannot initialize PolarSSL cipher context"); + } + if (method > RC4) { + cipher_set_padding_mode(evp, POLARSSL_PADDING_PKCS7); + } +#endif +} + +void cipher_context_set_iv(cipher_ctx_t *evp, uint8_t *iv, size_t iv_len, int enc) +{ + if (evp == NULL || iv == NULL) { + LOGE("cipher_context_set_keyiv(): Cipher context or IV is null"); + return; + } + if (enc) { + rand_bytes(iv, iv_len); + } +#if defined(USE_CRYPTO_OPENSSL) + if (!EVP_CipherInit_ex(evp, NULL, NULL, enc_key, iv, enc)) { + EVP_CIPHER_CTX_cleanup(evp); + FATAL("Cannot set key and IV"); + } +#elif defined(USE_CRYPTO_POLARSSL) + if (cipher_setkey(evp, enc_key, enc_key_len * 8, enc) != 0) { + cipher_free_ctx(evp); + FATAL("Cannot set PolarSSL cipher key"); + } + if (cipher_set_iv(evp, iv, iv_len) != 0) { + cipher_free_ctx(evp); + FATAL("Cannot set PolarSSL cipher IV"); + } + if(cipher_reset(evp) != 0) { + cipher_free_ctx(evp); + FATAL("Cannot finalize PolarSSL cipher context"); + } +#endif +#ifdef DEBUG + dump("IV", iv); +#endif +} + +void cipher_context_release(cipher_ctx_t *evp) { +#if defined(USE_CRYPTO_OPENSSL) + EVP_CIPHER_CTX_cleanup(evp); +#elif defined(USE_CRYPTO_POLARSSL) + cipher_free_ctx(evp); +#endif +} + +int cipher_context_update(cipher_ctx_t *evp, uint8_t *output, int *olen, \ + const uint8_t *input, int ilen) { +#if defined(USE_CRYPTO_OPENSSL) + return EVP_CipherUpdate(evp, (uint8_t *) output, (size_t *) olen, \ + (const uint8_t *) input, (size_t) ilen); +#elif defined(USE_CRYPTO_POLARSSL) + return !cipher_update(evp, (const uint8_t *) input, (size_t) ilen, \ + (uint8_t *) output, (size_t *) olen); +#endif +} + +char* ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method) +{ + if (method > TABLE) + { + cipher_ctx_t evp; + cipher_context_init(&evp, method, 1); int c_len = *len + BLOCK_SIZE; int iv_len = 0; int err = 0; char *ciphertext = malloc(max(iv_len + c_len, buf_size)); - uint8_t iv[EVP_MAX_IV_LENGTH]; + uint8_t iv[MAX_IV_LENGTH]; iv_len = enc_iv_len; - RAND_bytes(iv, iv_len); - EVP_CipherInit_ex(&evp, NULL, NULL, enc_key, iv, 1); + cipher_context_set_iv(&evp, iv, iv_len, 1); memcpy(ciphertext, iv, iv_len); -#ifdef DEBUG - dump("IV", iv); -#endif - - err = EVP_EncryptUpdate(&evp, (uint8_t*)(ciphertext+iv_len), - &c_len, (const uint8_t *)plaintext, *len); + err = cipher_context_update(&evp, (uint8_t*)(ciphertext+iv_len), + &c_len, (const uint8_t *)plaintext, *len); if (!err) { free(ciphertext); free(plaintext); - EVP_CIPHER_CTX_cleanup(&evp); + cipher_context_release(&evp); return NULL; } @@ -229,7 +553,7 @@ char* ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method) *len = iv_len + c_len; free(plaintext); - EVP_CIPHER_CTX_cleanup(&evp); + cipher_context_release(&evp); return ciphertext; @@ -257,19 +581,15 @@ char* ss_encrypt(int buf_size, char *plaintext, ssize_t *len, struct enc_ctx *ct if (!ctx->init) { - uint8_t iv[EVP_MAX_IV_LENGTH]; + uint8_t iv[MAX_IV_LENGTH]; iv_len = enc_iv_len; - RAND_bytes(iv, iv_len); - EVP_CipherInit_ex(&ctx->evp, NULL, NULL, enc_key, iv, 1); + cipher_context_set_iv(&ctx->evp, iv, iv_len, 1); memcpy(ciphertext, iv, iv_len); ctx->init = 1; -#ifdef DEBUG - dump("IV", iv); -#endif } - err = EVP_EncryptUpdate(&ctx->evp, (uint8_t*)(ciphertext+iv_len), - &c_len, (const uint8_t *)plaintext, *len); + err = cipher_context_update(&ctx->evp, (uint8_t*)(ciphertext+iv_len), + &c_len, (const uint8_t *)plaintext, *len); if (!err) { free(ciphertext); @@ -302,51 +622,26 @@ char* ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method) { if (method > TABLE) { - const EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]); - if (cipher == NULL) - { - LOGE("Cipher %s not found in OpenSSL library", supported_ciphers[method]); - FATAL("Cannot initialize cipher"); - } - EVP_CIPHER_CTX evp; - EVP_CIPHER_CTX_init(&evp); - if (!EVP_CipherInit_ex(&evp, cipher, NULL, NULL, NULL, 0)) - { - LOGE("Cannot initialize cipher %s", supported_ciphers[method]); - exit(EXIT_FAILURE); - } - if (!EVP_CIPHER_CTX_set_key_length(&evp, enc_key_len)) - { - EVP_CIPHER_CTX_cleanup(&evp); - LOGE("Invalid key length: %d", enc_key_len); - exit(EXIT_FAILURE); - } - if (method > RC4) - { - EVP_CIPHER_CTX_set_padding(&evp, 1); - } + cipher_ctx_t evp; + cipher_context_init(&evp, method, 0); int p_len = *len + BLOCK_SIZE; int iv_len = 0; int err = 0; char *plaintext = malloc(max(p_len, buf_size)); - uint8_t iv[EVP_MAX_IV_LENGTH]; + uint8_t iv[MAX_IV_LENGTH]; iv_len = enc_iv_len; memcpy(iv, ciphertext, iv_len); - EVP_CipherInit_ex(&evp, NULL, NULL, enc_key, iv, 0); - -#ifdef DEBUG - dump("IV", iv); -#endif + cipher_context_set_iv(&evp, iv, iv_len, 0); - err = EVP_DecryptUpdate(&evp, (uint8_t*)plaintext, &p_len, - (const uint8_t*)(ciphertext + iv_len), *len - iv_len); + err = cipher_context_update(&evp, (uint8_t*)plaintext, &p_len, + (const uint8_t*)(ciphertext + iv_len), *len - iv_len); if (!err) { free(ciphertext); free(plaintext); - EVP_CIPHER_CTX_cleanup(&evp); + cipher_context_release(&evp); return NULL; } @@ -357,7 +652,7 @@ char* ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method) *len = p_len; free(ciphertext); - EVP_CIPHER_CTX_cleanup(&evp); + cipher_context_release(&evp); return plaintext; } else @@ -383,18 +678,15 @@ char* ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *c if (!ctx->init) { - uint8_t iv[EVP_MAX_IV_LENGTH]; + uint8_t iv[MAX_IV_LENGTH]; iv_len = enc_iv_len; memcpy(iv, ciphertext, iv_len); - EVP_CipherInit_ex(&ctx->evp, NULL, NULL, enc_key, iv, 0); + cipher_context_set_iv(&ctx->evp, iv, iv_len, 0); ctx->init = 1; -#ifdef DEBUG - dump("IV", iv); -#endif } - err = EVP_DecryptUpdate(&ctx->evp, (uint8_t*)plaintext, &p_len, - (const uint8_t*)(ciphertext + iv_len), *len - iv_len); + err = cipher_context_update(&ctx->evp, (uint8_t*)plaintext, &p_len, + (const uint8_t*)(ciphertext + iv_len), *len - iv_len); if (!err) { @@ -426,50 +718,37 @@ char* ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *c void enc_ctx_init(int method, struct enc_ctx *ctx, int enc) { - const EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]); - if (cipher == NULL) - { - LOGE("Cipher %s not found in OpenSSL library", supported_ciphers[method]); - FATAL("Cannot initialize cipher"); - } memset(ctx, 0, sizeof(struct enc_ctx)); - - EVP_CIPHER_CTX *evp = &ctx->evp; - - EVP_CIPHER_CTX_init(evp); - if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc)) - { - LOGE("Cannot initialize cipher %s", supported_ciphers[method]); - exit(EXIT_FAILURE); - } - if (!EVP_CIPHER_CTX_set_key_length(evp, enc_key_len)) - { - EVP_CIPHER_CTX_cleanup(evp); - LOGE("Invalid key length: %d", enc_key_len); - exit(EXIT_FAILURE); - } - if (method > RC4) - { - EVP_CIPHER_CTX_set_padding(evp, 1); - } + cipher_context_init(&ctx->evp, method, enc); } void enc_key_init(int method, const char *pass) { + if (method <= TABLE || method >= CIPHER_NUM) { + LOGE("enc_key_init(): Illegal method"); + return; + } + +#if defined(USE_CRYPTO_OPENSSL) OpenSSL_add_all_algorithms(); +#endif - uint8_t iv[EVP_MAX_IV_LENGTH]; - const EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]); - if (cipher == NULL) - { - LOGE("Cipher %s not found in OpenSSL library", supported_ciphers[method]); + uint8_t iv[MAX_IV_LENGTH]; + const cipher_kt_t *cipher = get_cipher_type(method); + if (cipher == NULL) { + LOGE("Cipher %s not found in crypto library", supported_ciphers[method]); FATAL("Cannot initialize cipher"); - return; + } + const digest_type_t *md = get_digest_type("MD5"); + if (md == NULL) { + FATAL("MD5 Digest not found in crypto library"); } - enc_key_len = EVP_BytesToKey(cipher, EVP_md5(), NULL, (uint8_t *)pass, - strlen(pass), 1, enc_key, iv); - enc_iv_len = EVP_CIPHER_iv_length(cipher); + enc_key_len = bytes_to_key(cipher, md, (const uint8_t *) pass, enc_key, iv); + if (enc_key_len == 0) { + FATAL("Cannot generate key and IV"); + } + enc_iv_len = cipher_iv_size(cipher); } int enc_init(const char *pass, const char *method) diff --git a/src/encrypt.h b/src/encrypt.h index 65d62206..202b6553 100644 --- a/src/encrypt.h +++ b/src/encrypt.h @@ -21,7 +21,24 @@ #include #include +#if defined(USE_CRYPTO_OPENSSL) #include +typedef EVP_CIPHER cipher_kt_t; +typedef EVP_CIPHER_CTX cipher_ctx_t; +typedef EVP_MD digest_type_t; +#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH +#define MAX_IV_LENGTH EVP_MAX_IV_LENGTH +#define MAX_MD_SIZE EVP_MAX_MD_SIZE +#elif defined(USE_CRYPTO_POLARSSL) +#include +#include +typedef cipher_info_t cipher_kt_t; +typedef cipher_context_t cipher_ctx_t; +typedef md_info_t digest_type_t; +#define MAX_KEY_LENGTH 64 +#define MAX_IV_LENGTH POLARSSL_MAX_IV_LENGTH +#define MAX_MD_SIZE POLARSSL_MD_MAX_SIZE +#endif #ifdef HAVE_STDINT_H #include @@ -54,7 +71,7 @@ struct enc_ctx { uint8_t init; - EVP_CIPHER_CTX evp; + cipher_ctx_t evp; }; char* ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method); @@ -64,5 +81,7 @@ char* ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *c void enc_ctx_init(int method, struct enc_ctx *ctx, int enc); int enc_init(const char *pass, const char *method); int enc_get_iv_len(void); +void cipher_context_release(cipher_ctx_t *evp); +unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md); #endif // _ENCRYPT_H diff --git a/src/local.c b/src/local.c index 867cc17d..5a69aa13 100644 --- a/src/local.c +++ b/src/local.c @@ -700,12 +700,12 @@ static void free_server(struct server *server) } if (server->e_ctx != NULL) { - EVP_CIPHER_CTX_cleanup(&server->e_ctx->evp); + cipher_context_release(&server->e_ctx->evp); free(server->e_ctx); } if (server->d_ctx != NULL) { - EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp); + cipher_context_release(&server->d_ctx->evp); free(server->d_ctx); } if (server->buf) diff --git a/src/udprelay.c b/src/udprelay.c index 65b3928a..ff30107b 100644 --- a/src/udprelay.c +++ b/src/udprelay.c @@ -31,8 +31,6 @@ #include "win32.h" #endif -#include - #include "utils.h" #include "udprelay.h" #include "cache.h" @@ -89,7 +87,7 @@ static char *hash_key(const char *header, const int header_len, const struct soc memcpy(key, addr, sizeof(struct sockaddr)); memcpy(key + sizeof(struct sockaddr), header, header_len); - return (char*) MD5((const uint8_t *)key, sizeof(struct sockaddr) + header_len, NULL); + return (char*) enc_md5((const uint8_t *)key, sizeof(struct sockaddr) + header_len, NULL); } static int parse_udprealy_header(const char* buf, const int buf_len, char *host, char *port)