| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| This is the original author Dscho's account on the project's initial history. | ||
| If you want to know what happened afterwards, have a look at [NEWS](NEWS.md). | ||
|
|
||
| History | ||
| ======= | ||
|
|
||
| LibVNCServer is based on Tridia VNC and OSXvnc, which in turn are based on | ||
| the original code from ORL/AT&T. | ||
|
|
||
| When I began hacking with computers, my first interest was speed. So, when I | ||
| got around assembler, I programmed the floppy to do much of the work, because | ||
| its clock rate was higher than that of my C64. This was my first experience | ||
| with client/server techniques. | ||
|
|
||
| When I came around Xwindows (much later), I was at once intrigued by the | ||
| elegance of such connectedness between the different computers. I used it | ||
| a lot - not the least priority lay on games. However, when I tried it over | ||
| modem from home, it was no longer that much fun. | ||
|
|
||
| When I started working with ASP (Application Service Provider) programs, I | ||
| tumbled across Tarantella and Citrix. Being a security fanatic, the idea of | ||
| running a server on windows didn't appeal to me, so Citrix went down the | ||
| basket. However, Tarantella has its own problems (security as well as the | ||
| high price). But at the same time somebody told me about this "great little | ||
| administrator's tool" named VNC. Being used to windows programs' sizes, the | ||
| surprise was reciprocal inverse to the size of VNC! | ||
|
|
||
| At the same time, the program "rdesktop" (a native Linux client for the | ||
| Terminal Services of Windows servers) came to my attention. There where even | ||
| works under way to make a protocol converter "rdp2vnc" out of this. However, | ||
| my primary goal was a slow connection and rdp2vnc could only speak RRE | ||
| encoding, which is not that funny with just 5kB/s. Tim Edmonds, the original | ||
| author of rdp2vnc, suggested that I adapt it to Hextile Encoding, which is | ||
| better. I first tried that, but had no success at all (crunchy pictures). | ||
|
|
||
| Also, I liked the idea of an HTTP server included and possibly other | ||
| encodings like the Tight Encodings from Const Kaplinsky. So I started looking | ||
| for libraries implementing a VNC server where I could steal what I can't make. | ||
| I found some programs based on the demo server from AT&T, which was also the | ||
| basis for rdp2vnc (can only speak Raw and RRE encoding). There were some | ||
| rumors that GGI has a VNC backend, but I didn't find any code, so probably | ||
| there wasn't a working version anyway. | ||
|
|
||
| All of a sudden, everything changed: I read on freshmeat that "OSXvnc" was | ||
| released. I looked at the code and it was not much of a problem to work out | ||
| a simple server - using every functionality there is in Xvnc. It became clear | ||
| to me that I *had* to build a library out of it, so everybody can use it. | ||
| Every change, every new feature can propagate to every user of it. | ||
|
|
||
| It also makes everything easier: | ||
| You don't care about the cursor, once set (or use the standard cursor). | ||
| You don't care about those sockets. You don't care about encodings. | ||
| You just change your frame buffer and inform the library about it. Every once | ||
| in a while you call rfbProcessEvents and that's it. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # Security Policy | ||
|
|
||
| ## Supported Versions | ||
|
|
||
| We fix security problems on the master branch. Downstream packagers are | ||
| advised to cherry-pick those onto release versions. Currently, no point | ||
| releases of already-released versions are made due to low development | ||
| team head count. | ||
|
|
||
| ## Reporting a Vulnerability | ||
|
|
||
| Mail in to dontmind@sdf.org. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| high-prio: | ||
| ---------- | ||
| - [Merge MulticastVNC](https://github.com/LibVNC/libvncserver/issues/394) | ||
| - [style fixes: use Linux' coding guidelines & ANSIfy tightvnc-filetransfer](https://github.com/LibVNC/libvncserver/issues/395) | ||
| - [Implement encryption in libvncserver](https://github.com/LibVNC/libvncserver/issues/396) | ||
|
|
||
|
|
||
| maybe-later: | ||
| ------------ | ||
|
|
||
| - selectbox: scroll bars | ||
| - authentification schemes (secure vnc) | ||
| - IO function ptr exists; now explain how to tunnel and implement a | ||
| - client address restriction scheme. | ||
|
|
||
| - make SDLvncviewer more versatile | ||
| - test for missing keys (especially "[]{}" with ./examples/mac), | ||
| - map Apple/Linux/Windows keys onto each other, | ||
| - handle selection | ||
| - handle scroll wheel | ||
| - LibVNCClient cleanup: prefix with "rfbClient", and make sure it does | ||
| not deliberately die() or exit() anywhere! | ||
| - make corre work again (libvncclient or libvncserver?) | ||
| - teach SDLvncviewer about CopyRect... | ||
| - implement "-record" in libvncclient | ||
| - implement QoS for Windows in libvncclient |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # the name of the target operating system | ||
| SET(CMAKE_SYSTEM_NAME Windows) | ||
|
|
||
| # Choose an appropriate compiler prefix | ||
|
|
||
| # for classical mingw32 | ||
| # see http://www.mingw.org/ | ||
| #set(COMPILER_PREFIX "i586-mingw32msvc") | ||
|
|
||
| # for 32 or 64 bits mingw-w64 | ||
| # see http://mingw-w64.sourceforge.net/ | ||
| set(COMPILER_PREFIX "i686-w64-mingw32") | ||
| #set(COMPILER_PREFIX "x86_64-w64-mingw32" | ||
|
|
||
| # which compilers to use for C and C++ | ||
| find_program(CMAKE_RC_COMPILER NAMES ${COMPILER_PREFIX}-windres) | ||
| #SET(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres) | ||
| find_program(CMAKE_C_COMPILER NAMES ${COMPILER_PREFIX}-gcc) | ||
| #SET(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc) | ||
| find_program(CMAKE_CXX_COMPILER NAMES ${COMPILER_PREFIX}-g++) | ||
| #SET(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++) | ||
|
|
||
|
|
||
| # here is the target environment located | ||
| SET(USER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/deps) | ||
| SET(CMAKE_FIND_ROOT_PATH /usr/${COMPILER_PREFIX} ${USER_ROOT_PATH}) | ||
|
|
||
| # adjust the default behaviour of the FIND_XXX() commands: | ||
| # search headers and libraries in the target environment, search | ||
| # programs in the host environment | ||
| set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | ||
| set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | ||
| set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) | ||
|
|
||
| # use wine for runnings tests | ||
| set(CMAKE_CROSSCOMPILING_EMULATOR wine) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| #ifndef _RFB_CRYPTO_H | ||
| #define _RFB_CRYPTO_H 1 | ||
|
|
||
| #include <stdint.h> | ||
| #include "rfb/rfbconfig.h" | ||
|
|
||
| #define SHA1_HASH_SIZE 20 | ||
| #define MD5_HASH_SIZE 16 | ||
|
|
||
| /* Generates an MD5 hash of 'in' and writes it to 'out', which must be 16 bytes in size. */ | ||
| int hash_md5(void *out, const void *in, const size_t in_len); | ||
|
|
||
| /* Generates an SHA1 hash of 'in' and writes it to 'out', which must be 20 bytes in size. */ | ||
| int hash_sha1(void *out, const void *in, const size_t in_len); | ||
|
|
||
| /* Fill 'out' with 'len' random bytes. */ | ||
| void random_bytes(void *out, size_t len); | ||
|
|
||
| /* | ||
| Takes the 8-byte key in 'key', reverses the bits in each byte of key as required by the RFB protocol, | ||
| encrypts 'in' with the resulting key using single-key 56-bit DES and writes the result to 'out'. | ||
| */ | ||
| int encrypt_rfbdes(void *out, int *out_len, const unsigned char key[8], const void *in, const size_t in_len); | ||
|
|
||
| /* | ||
| Takes the 8-byte key in 'key', reverses the bits in each byte of key as required by the RFB protocol, | ||
| decrypts 'in' with the resulting key using single-key 56-bit DES and writes the result to 'out'. | ||
| */ | ||
| int decrypt_rfbdes(void *out, int *out_len, const unsigned char key[8], const void *in, const size_t in_len); | ||
|
|
||
| /* Encrypts 'in' with the the 16-byte key in 'key' using AES-128-ECB and writes the result to 'out'. */ | ||
| int encrypt_aes128ecb(void *out, int *out_len, const unsigned char key[16], const void *in, const size_t in_len); | ||
|
|
||
| /* | ||
| Generates a Diffie-Hellman public-private keypair using the generator value 'gen' and prime modulo | ||
| 'prime', writing the result to 'pub_out' and 'priv_out', which must be 'keylen' in size. | ||
| */ | ||
| int dh_generate_keypair(uint8_t *priv_out, uint8_t *pub_out, const uint8_t *gen, const size_t gen_len, const uint8_t *prime, const size_t keylen); | ||
|
|
||
| /* | ||
| Computes the shared Diffie-Hellman secret using the private key 'priv', the other side's public | ||
| key 'pub' and the modulo prime 'prime' and writes it to 'shared_out', which must be 'keylen' in size. | ||
| */ | ||
| int dh_compute_shared_key(uint8_t *shared_out, const uint8_t *priv, const uint8_t *pub, const uint8_t *prime, const size_t keylen); | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| /* | ||
| * crypto_included.c - Crypto wrapper (included version) | ||
| */ | ||
|
|
||
| /* | ||
| * Copyright (C) 2011 Gernot Tenchio | ||
| * Copyright (C) 2019 Christian Beier | ||
| * | ||
| * This is free software; you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation; either version 2 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This software is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this software; if not, write to the Free Software | ||
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | ||
| * USA. | ||
| */ | ||
|
|
||
| #include <string.h> | ||
| #include "sha.h" | ||
| #include "d3des.h" | ||
| #include "crypto.h" | ||
|
|
||
|
|
||
| int hash_md5(void *out, const void *in, const size_t in_len) | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| int hash_sha1(void *out, const void *in, const size_t in_len) | ||
| { | ||
| SHA1Context sha1; | ||
| if(SHA1Reset(&sha1) != shaSuccess) | ||
| return 0; | ||
| if(SHA1Input(&sha1, in, in_len) != shaSuccess) | ||
| return 0; | ||
| if(SHA1Result(&sha1, out) != shaSuccess) | ||
| return 0; | ||
|
|
||
| return 1; | ||
| } | ||
|
|
||
| void random_bytes(void *out, size_t len) | ||
| { | ||
|
|
||
| } | ||
|
|
||
| int encrypt_rfbdes(void *out, int *out_len, const unsigned char key[8], const void *in, const size_t in_len) | ||
| { | ||
| int eightbyteblocks = in_len/8; | ||
| int i; | ||
| rfbDesKey((unsigned char*)key, EN0); | ||
| for(i = 0; i < eightbyteblocks; ++i) | ||
| rfbDes((unsigned char*)in + i*8, (unsigned char*)out + i*8); | ||
|
|
||
| *out_len = in_len; | ||
|
|
||
| return 1; | ||
| } | ||
|
|
||
| int decrypt_rfbdes(void *out, int *out_len, const unsigned char key[8], const void *in, const size_t in_len) | ||
| { | ||
| int eightbyteblocks = in_len/8; | ||
| int i; | ||
| rfbDesKey((unsigned char*)key, DE1); | ||
| for(i = 0; i < eightbyteblocks; ++i) | ||
| rfbDes((unsigned char*)in + i*8, (unsigned char*)out + i*8); | ||
|
|
||
| *out_len = in_len; | ||
|
|
||
| return 1; | ||
| } | ||
|
|
||
| int encrypt_aes128ecb(void *out, int *out_len, const unsigned char key[16], const void *in, const size_t in_len) | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| int dh_generate_keypair(uint8_t *priv_out, uint8_t *pub_out, const uint8_t *gen, const size_t gen_len, const uint8_t *prime, const size_t keylen) | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| int dh_compute_shared_key(uint8_t *shared_out, const uint8_t *priv, const uint8_t *pub, const uint8_t *prime, const size_t keylen) | ||
| { | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,271 @@ | ||
| /* | ||
| * crypto_gnutls.c - Crypto wrapper (libgcrypt version) | ||
| */ | ||
|
|
||
| /* | ||
| * Copyright (C) 2011 Gernot Tenchio | ||
| * Copyright (C) 2019 Christian Beier | ||
| * | ||
| * This is free software; you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation; either version 2 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This software is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this software; if not, write to the Free Software | ||
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | ||
| * USA. | ||
| */ | ||
|
|
||
| #include <string.h> | ||
| #include <gcrypt.h> | ||
| #include "crypto.h" | ||
|
|
||
| static int mpiToBytes(const gcry_mpi_t value, uint8_t *result, size_t size) | ||
| { | ||
| gcry_error_t error; | ||
| size_t len; | ||
| int i; | ||
|
|
||
| error = gcry_mpi_print(GCRYMPI_FMT_USG, result, size, &len, value); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| return 0; | ||
| for (i=size-1;i>(int)size-1-(int)len;--i) | ||
| result[i] = result[i-size+len]; | ||
| for (;i>=0;--i) | ||
| result[i] = 0; | ||
| return 1; | ||
| } | ||
|
|
||
| static unsigned char reverseByte(unsigned char b) { | ||
| b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; | ||
| b = (b & 0xCC) >> 2 | (b & 0x33) << 2; | ||
| b = (b & 0xAA) >> 1 | (b & 0x55) << 1; | ||
| return b; | ||
| } | ||
|
|
||
| int hash_md5(void *out, const void *in, const size_t in_len) | ||
| { | ||
| int result = 0; | ||
| gcry_error_t error; | ||
| gcry_md_hd_t md5 = NULL; | ||
| void *digest; | ||
|
|
||
| error = gcry_md_open(&md5, GCRY_MD_MD5, 0); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| gcry_md_write(md5, in, in_len); | ||
|
|
||
| if(!(digest = gcry_md_read(md5, GCRY_MD_MD5))) | ||
| goto out; | ||
|
|
||
| memcpy(out, digest, gcry_md_get_algo_dlen(GCRY_MD_MD5)); | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| gcry_md_close(md5); | ||
| return result; | ||
| } | ||
|
|
||
| int hash_sha1(void *out, const void *in, const size_t in_len) | ||
| { | ||
| int result = 0; | ||
| gcry_error_t error; | ||
| gcry_md_hd_t sha1 = NULL; | ||
| void *digest; | ||
|
|
||
| error = gcry_md_open(&sha1, GCRY_MD_SHA1, 0); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| gcry_md_write(sha1, in, in_len); | ||
|
|
||
| if(!(digest = gcry_md_read(sha1, GCRY_MD_SHA1))) | ||
| goto out; | ||
|
|
||
| memcpy(out, digest, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| gcry_md_close(sha1); | ||
| return result; | ||
| } | ||
|
|
||
| void random_bytes(void *out, size_t len) | ||
| { | ||
| gcry_randomize(out, len, GCRY_STRONG_RANDOM); | ||
| } | ||
|
|
||
| int encrypt_rfbdes(void *out, int *out_len, const unsigned char key[8], const void *in, const size_t in_len) | ||
| { | ||
| int result = 0; | ||
| gcry_error_t error; | ||
| gcry_cipher_hd_t des = NULL; | ||
| unsigned char mungedkey[8]; | ||
| int i; | ||
|
|
||
| for (i = 0; i < 8; i++) | ||
| mungedkey[i] = reverseByte(key[i]); | ||
|
|
||
| error = gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| error = gcry_cipher_setkey(des, mungedkey, 8); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| error = gcry_cipher_encrypt(des, out, in_len, in, in_len); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| *out_len = in_len; | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| gcry_cipher_close(des); | ||
| return result; | ||
| } | ||
|
|
||
| int decrypt_rfbdes(void *out, int *out_len, const unsigned char key[8], const void *in, const size_t in_len) | ||
| { | ||
| int result = 0; | ||
| gcry_error_t error; | ||
| gcry_cipher_hd_t des = NULL; | ||
| unsigned char mungedkey[8]; | ||
| int i; | ||
|
|
||
| for (i = 0; i < 8; i++) | ||
| mungedkey[i] = reverseByte(key[i]); | ||
|
|
||
| error = gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| error = gcry_cipher_setkey(des, mungedkey, 8); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| error = gcry_cipher_decrypt(des, out, in_len, in, in_len); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| *out_len = in_len; | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| gcry_cipher_close(des); | ||
| return result; | ||
| } | ||
|
|
||
|
|
||
| int encrypt_aes128ecb(void *out, int *out_len, const unsigned char key[16], const void *in, const size_t in_len) | ||
| { | ||
| int result = 0; | ||
| gcry_error_t error; | ||
| gcry_cipher_hd_t aes = NULL; | ||
|
|
||
| error = gcry_cipher_open(&aes, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| error = gcry_cipher_setkey(aes, key, 16); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| error = gcry_cipher_encrypt(aes, out, in_len, in, in_len); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
| *out_len = in_len; | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| gcry_cipher_close(aes); | ||
| return result; | ||
| } | ||
|
|
||
| int dh_generate_keypair(uint8_t *priv_out, uint8_t *pub_out, const uint8_t *gen, const size_t gen_len, const uint8_t *prime, const size_t keylen) | ||
| { | ||
| int result = 0; | ||
| gcry_error_t error; | ||
| gcry_mpi_t genmpi = NULL, modmpi = NULL, privmpi = NULL, pubmpi = NULL; | ||
|
|
||
| error = gcry_mpi_scan(&genmpi, GCRYMPI_FMT_USG, gen, gen_len, NULL); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
| error = gcry_mpi_scan(&modmpi, GCRYMPI_FMT_USG, prime, keylen, NULL); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| privmpi = gcry_mpi_new(keylen); | ||
| if (!privmpi) | ||
| goto out; | ||
| gcry_mpi_randomize(privmpi, (keylen/8)*8, GCRY_STRONG_RANDOM); | ||
|
|
||
| pubmpi = gcry_mpi_new(keylen); | ||
| if (!pubmpi) | ||
| goto out; | ||
|
|
||
| gcry_mpi_powm(pubmpi, genmpi, privmpi, modmpi); | ||
|
|
||
| if (!mpiToBytes(pubmpi, pub_out, keylen)) | ||
| goto out; | ||
| if (!mpiToBytes(privmpi, priv_out, keylen)) | ||
| goto out; | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| gcry_mpi_release(genmpi); | ||
| gcry_mpi_release(modmpi); | ||
| gcry_mpi_release(privmpi); | ||
| gcry_mpi_release(pubmpi); | ||
| return result; | ||
| } | ||
|
|
||
| int dh_compute_shared_key(uint8_t *shared_out, const uint8_t *priv, const uint8_t *pub, const uint8_t *prime, const size_t keylen) | ||
| { | ||
| int result = 1; | ||
| gcry_error_t error; | ||
| gcry_mpi_t keympi = NULL, modmpi = NULL, privmpi = NULL, pubmpi = NULL; | ||
|
|
||
| error = gcry_mpi_scan(&privmpi, GCRYMPI_FMT_USG, priv, keylen, NULL); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
| error = gcry_mpi_scan(&pubmpi, GCRYMPI_FMT_USG, pub, keylen, NULL); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
| error = gcry_mpi_scan(&modmpi, GCRYMPI_FMT_USG, prime, keylen, NULL); | ||
| if (gcry_err_code(error) != GPG_ERR_NO_ERROR) | ||
| goto out; | ||
|
|
||
| keympi = gcry_mpi_new(keylen); | ||
| if (!keympi) | ||
| goto out; | ||
|
|
||
| gcry_mpi_powm(keympi, pubmpi, privmpi, modmpi); | ||
|
|
||
| if (!mpiToBytes(keympi, shared_out, keylen)) | ||
| goto out; | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| gcry_mpi_release(keympi); | ||
| gcry_mpi_release(modmpi); | ||
| gcry_mpi_release(privmpi); | ||
| gcry_mpi_release(pubmpi); | ||
|
|
||
| return result; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,201 @@ | ||
| /* | ||
| * crypto_openssl.c - Crypto wrapper (openssl version) | ||
| */ | ||
|
|
||
| /* | ||
| * Copyright (C) 2011 Gernot Tenchio | ||
| * Copyright (C) 2019 Christian Beier | ||
| * | ||
| * This is free software; you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation; either version 2 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This software is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this software; if not, write to the Free Software | ||
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | ||
| * USA. | ||
| */ | ||
|
|
||
| #include <string.h> | ||
| #include <openssl/sha.h> | ||
| #include <openssl/md5.h> | ||
| #include <openssl/dh.h> | ||
| #include <openssl/evp.h> | ||
| #include <openssl/rand.h> | ||
| #include "crypto.h" | ||
|
|
||
| static unsigned char reverseByte(unsigned char b) { | ||
| b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; | ||
| b = (b & 0xCC) >> 2 | (b & 0x33) << 2; | ||
| b = (b & 0xAA) >> 1 | (b & 0x55) << 1; | ||
| return b; | ||
| } | ||
|
|
||
| int hash_md5(void *out, const void *in, const size_t in_len) | ||
| { | ||
| MD5_CTX md5; | ||
| if(!MD5_Init(&md5)) | ||
| return 0; | ||
| if(!MD5_Update(&md5, in, in_len)) | ||
| return 0; | ||
| if(!MD5_Final(out, &md5)) | ||
| return 0; | ||
| return 1; | ||
| } | ||
|
|
||
| int hash_sha1(void *out, const void *in, const size_t in_len) | ||
| { | ||
| SHA_CTX sha1; | ||
| if(!SHA1_Init(&sha1)) | ||
| return 0; | ||
| if(!SHA1_Update(&sha1, in, in_len)) | ||
| return 0; | ||
| if(!SHA1_Final(out, &sha1)) | ||
| return 0; | ||
| return 1; | ||
| } | ||
|
|
||
| void random_bytes(void *out, size_t len) | ||
| { | ||
| RAND_bytes(out, len); | ||
| } | ||
|
|
||
| int encrypt_rfbdes(void *out, int *out_len, const unsigned char key[8], const void *in, const size_t in_len) | ||
| { | ||
| int result = 0; | ||
| EVP_CIPHER_CTX *des; | ||
| unsigned char mungedkey[8]; | ||
| int i; | ||
|
|
||
| for (i = 0; i < 8; i++) | ||
| mungedkey[i] = reverseByte(key[i]); | ||
|
|
||
| if(!(des = EVP_CIPHER_CTX_new())) | ||
| goto out; | ||
| if(!EVP_EncryptInit_ex(des, EVP_des_ecb(), NULL, mungedkey, NULL)) | ||
| goto out; | ||
| if(!EVP_EncryptUpdate(des, out, out_len, in, in_len)) | ||
| goto out; | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| EVP_CIPHER_CTX_free(des); | ||
| return result; | ||
| } | ||
|
|
||
| int decrypt_rfbdes(void *out, int *out_len, const unsigned char key[8], const void *in, const size_t in_len) | ||
| { | ||
| int result = 0; | ||
| EVP_CIPHER_CTX *des; | ||
| unsigned char mungedkey[8]; | ||
| int i; | ||
|
|
||
| for (i = 0; i < 8; i++) | ||
| mungedkey[i] = reverseByte(key[i]); | ||
|
|
||
| if(!(des = EVP_CIPHER_CTX_new())) | ||
| goto out; | ||
| if(!EVP_DecryptInit_ex(des, EVP_des_ecb(), NULL, mungedkey, NULL)) | ||
| goto out; | ||
| if(!EVP_DecryptUpdate(des, out, out_len, in, in_len)) | ||
| goto out; | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| EVP_CIPHER_CTX_free(des); | ||
| return result; | ||
| } | ||
|
|
||
| int encrypt_aes128ecb(void *out, int *out_len, const unsigned char key[16], const void *in, const size_t in_len) | ||
| { | ||
| int result = 0; | ||
| EVP_CIPHER_CTX *aes; | ||
|
|
||
| if(!(aes = EVP_CIPHER_CTX_new())) | ||
| goto out; | ||
| EVP_CIPHER_CTX_set_padding(aes, 0); | ||
| if(!EVP_EncryptInit_ex(aes, EVP_aes_128_ecb(), NULL, key, NULL)) | ||
| goto out; | ||
| if(!EVP_EncryptUpdate(aes, out, out_len, in, in_len)) | ||
| goto out; | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| EVP_CIPHER_CTX_free(aes); | ||
| return result; | ||
| } | ||
|
|
||
| int dh_generate_keypair(uint8_t *priv_out, uint8_t *pub_out, const uint8_t *gen, const size_t gen_len, const uint8_t *prime, const size_t keylen) | ||
| { | ||
| int result = 0; | ||
| DH *dh; | ||
| #if OPENSSL_VERSION_NUMBER >= 0x10100000L | ||
| const BIGNUM *pub_key = NULL; | ||
| const BIGNUM *priv_key = NULL; | ||
| #endif | ||
|
|
||
| if(!(dh = DH_new())) | ||
| goto out; | ||
| #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER | ||
| dh->p = BN_bin2bn(prime, keylen, NULL); | ||
| dh->g = BN_bin2bn(gen, gen_len, NULL); | ||
| #else | ||
| if(!DH_set0_pqg(dh, BN_bin2bn(prime, keylen, NULL), NULL, BN_bin2bn(gen, gen_len, NULL))) | ||
| goto out; | ||
| #endif | ||
| if(!DH_generate_key(dh)) | ||
| goto out; | ||
| #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER | ||
| if(BN_bn2bin(dh->priv_key, priv_out) == 0) | ||
| goto out; | ||
| if(BN_bn2bin(dh->pub_key, pub_out) == 0) | ||
| goto out; | ||
| #else | ||
| DH_get0_key(dh, &pub_key, &priv_key); | ||
| if(BN_bn2binpad(priv_key, priv_out, keylen) == -1) | ||
| goto out; | ||
| if(BN_bn2binpad(pub_key, pub_out, keylen) == -1) | ||
| goto out; | ||
| #endif | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| DH_free(dh); | ||
| return result; | ||
| } | ||
|
|
||
| int dh_compute_shared_key(uint8_t *shared_out, const uint8_t *priv, const uint8_t *pub, const uint8_t *prime, const size_t keylen) | ||
| { | ||
| int result = 0; | ||
| DH *dh; | ||
|
|
||
| if(!(dh = DH_new())) | ||
| goto out; | ||
| #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER | ||
| dh->p = BN_bin2bn(prime, keylen, NULL); | ||
| dh->priv_key = BN_bin2bn(priv, keylen, NULL); | ||
| #else | ||
| if(!DH_set0_pqg(dh, BN_bin2bn(prime, keylen, NULL), NULL, BN_new())) | ||
| goto out; | ||
| if(!DH_set0_key(dh, NULL, BN_bin2bn(priv, keylen, NULL))) | ||
| goto out; | ||
| #endif | ||
| if(DH_compute_key(shared_out, BN_bin2bn(pub, keylen, NULL), dh) == -1) | ||
| goto out; | ||
|
|
||
| result = 1; | ||
|
|
||
| out: | ||
| DH_free(dh); | ||
| return result; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| /* | ||
| * LibVNCServer/LibVNCClient common platform socket defines and includes. | ||
| * | ||
| * Copyright (C) 2020 Christian Beier <dontmind@freeshell.org> | ||
| * | ||
| * This is free software; you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation; either version 2 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This software is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this software; if not, write to the Free Software | ||
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | ||
| * USA. | ||
| */ | ||
|
|
||
| #ifndef _RFB_COMMON_SOCKETS_H | ||
| #define _RFB_COMMON_SOCKETS_H | ||
|
|
||
| #ifdef WIN32 | ||
| /* | ||
| Windows sockets | ||
| */ | ||
| #include <winsock2.h> | ||
| #include <ws2tcpip.h> | ||
|
|
||
| #undef EWOULDBLOCK | ||
| #define EWOULDBLOCK WSAEWOULDBLOCK | ||
|
|
||
| #undef ETIMEDOUT | ||
| #define ETIMEDOUT WSAETIMEDOUT | ||
|
|
||
| #undef EINTR | ||
| #define EINTR WSAEINTR | ||
|
|
||
| #undef EINVAL | ||
| #define EINVAL WSAEINVAL | ||
|
|
||
| /* MinGW has those, but MSVC not */ | ||
| #ifdef _MSC_VER | ||
| #define SHUT_RD SD_RECEIVE | ||
| #define SHUT_WR SD_SEND | ||
| #define SHUT_RDWR SD_BOTH | ||
| #endif | ||
|
|
||
| #define read(sock,buf,len) recv(sock,buf,len,0) | ||
| #define write(sock,buf,len) send(sock,buf,len,0) | ||
|
|
||
| #else | ||
| /* | ||
| Unix sockets | ||
| */ | ||
| #include <sys/socket.h> | ||
| #include <sys/un.h> | ||
| #include <netinet/in.h> | ||
| #include <arpa/inet.h> | ||
| #include <netinet/tcp.h> | ||
| #include <netdb.h> | ||
| #endif | ||
|
|
||
| #endif /* _RFB_COMMON_SOCKETS_H */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,7 @@ | ||
| /** | ||
| @example blooptest.c | ||
| blooptest is a test of pthreads. It is just the example, but with a background | ||
| loop to hunt down thread lockups. | ||
| */ | ||
| #define BACKGROUND_LOOP_TEST | ||
| #include "example.c" |