Line data Source code
1 : /*
2 : Mosh: the mobile shell
3 : Copyright 2012 Keith Winstein
4 :
5 : This program is free software: you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as published by
7 : the Free Software Foundation, either version 3 of the License, or
8 : (at your option) any later version.
9 :
10 : This program is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public License
16 : along with this program. If not, see <http://www.gnu.org/licenses/>.
17 :
18 : In addition, as a special exception, the copyright holders give
19 : permission to link the code of portions of this program with the
20 : OpenSSL library under certain conditions as described in each
21 : individual source file, and distribute linked combinations including
22 : the two.
23 :
24 : You must obey the GNU General Public License in all respects for all
25 : of the code used other than OpenSSL. If you modify file(s) with this
26 : exception, you may extend this exception to your version of the
27 : file(s), but you are not obligated to do so. If you do not wish to do
28 : so, delete this exception statement from your version. If you delete
29 : this exception statement from all source files in the program, then
30 : also delete it here.
31 : */
32 :
33 : #include <string.h>
34 : #include <stdio.h>
35 : #include <errno.h>
36 : #include <stdlib.h>
37 : #include <assert.h>
38 : #include <sys/resource.h>
39 : #include <fstream>
40 :
41 : #include "byteorder.h"
42 : #include "crypto.h"
43 : #include "base64.h"
44 : #include "fatal_assert.h"
45 : #include "prng.h"
46 :
47 : using namespace Crypto;
48 :
49 452 : long int myatoi( const char *str )
50 : {
51 452 : char *end;
52 :
53 452 : errno = 0;
54 452 : long int ret = strtol( str, &end, 10 );
55 :
56 452 : if ( ( errno != 0 )
57 452 : || ( end != str + strlen( str ) ) ) {
58 0 : throw CryptoException( "Bad integer." );
59 : }
60 :
61 452 : return ret;
62 : }
63 :
64 8005333 : uint64_t Crypto::unique( void )
65 : {
66 8005333 : static uint64_t counter = 0;
67 8005333 : uint64_t rv = counter++;
68 8005333 : if ( counter == 0 ) {
69 0 : throw CryptoException( "Counter wrapped", true );
70 : }
71 8005333 : return rv;
72 : }
73 :
74 13590 : AlignedBuffer::AlignedBuffer( size_t len, const char *data )
75 13590 : : m_len( len ), m_allocated( NULL ), m_data( NULL )
76 : {
77 13590 : size_t alloc_len = len ? len : 1;
78 : #if defined(HAVE_POSIX_MEMALIGN)
79 13590 : if ( ( 0 != posix_memalign( &m_allocated, 16, alloc_len ) )
80 13590 : || ( m_allocated == NULL ) ) {
81 0 : throw std::bad_alloc();
82 : }
83 13590 : m_data = (char *) m_allocated;
84 :
85 : #else
86 : /* malloc() a region 15 bytes larger than we need, and find
87 : the aligned offset within. */
88 : m_allocated = malloc( 15 + alloc_len );
89 : if ( m_allocated == NULL ) {
90 : throw std::bad_alloc();
91 : }
92 :
93 : uintptr_t iptr = (uintptr_t) m_allocated;
94 : if ( iptr & 0xF ) {
95 : iptr += 16 - ( iptr & 0xF );
96 : }
97 : assert( !( iptr & 0xF ) );
98 : assert( iptr >= (uintptr_t) m_allocated );
99 : assert( iptr <= ( 15 + (uintptr_t) m_allocated ) );
100 :
101 : m_data = (char *) iptr;
102 :
103 : #endif /* !defined(HAVE_POSIX_MEMALIGN) */
104 :
105 13590 : if ( data ) {
106 2900 : memcpy( m_data, data, len );
107 : }
108 13590 : }
109 :
110 262592 : Base64Key::Base64Key( string printable_key )
111 : {
112 262592 : if ( printable_key.length() != 22 ) {
113 0 : throw CryptoException( "Key must be 22 letters long." );
114 : }
115 :
116 262592 : string base64 = printable_key + "==";
117 :
118 262592 : size_t len = 16;
119 262592 : if ( !base64_decode( base64.data(), 24, key, &len ) ) {
120 0 : throw CryptoException( "Key must be well-formed base64." );
121 : }
122 :
123 262592 : if ( len != 16 ) {
124 0 : throw CryptoException( "Key must represent 16 octets." );
125 : }
126 :
127 : /* to catch changes after the first 128 bits */
128 525184 : if ( printable_key != this->printable_key() ) {
129 0 : throw CryptoException( "Base64 key was not encoded 128-bit key." );
130 : }
131 262592 : }
132 :
133 580 : Base64Key::Base64Key()
134 : {
135 580 : PRNG().fill( key, sizeof( key ) );
136 580 : }
137 :
138 262144 : Base64Key::Base64Key(PRNG &prng)
139 : {
140 262144 : prng.fill( key, sizeof( key ) );
141 262144 : }
142 :
143 1049476 : string Base64Key::printable_key( void ) const
144 : {
145 1049476 : char base64[ 24 ];
146 :
147 1049476 : base64_encode( key, 16, base64, 24 );
148 :
149 1049476 : if ( (base64[ 23 ] != '=')
150 1049476 : || (base64[ 22 ] != '=') ) {
151 0 : throw CryptoException( string( "Unexpected output from base64_encode: " ) + string( base64, 24 ) );
152 : }
153 :
154 1049476 : base64[ 22 ] = 0;
155 1049476 : return string( base64 );
156 : }
157 :
158 1156 : Session::Session( Base64Key s_key )
159 1156 : : key( s_key ), ctx_buf( ae_ctx_sizeof() ),
160 1156 : ctx( (ae_ctx *)ctx_buf.data() ), blocks_encrypted( 0 ),
161 1156 : plaintext_buffer( RECEIVE_MTU ),
162 1156 : ciphertext_buffer( RECEIVE_MTU ),
163 1156 : nonce_buffer( Nonce::NONCE_LEN )
164 : {
165 1156 : if ( AE_SUCCESS != ae_init( ctx, key.data(), 16, 12, 16 ) ) {
166 0 : throw CryptoException( "Could not initialize AES-OCB context." );
167 : }
168 1156 : }
169 :
170 1608 : Session::~Session()
171 : {
172 1608 : fatal_assert( ae_clear( ctx ) == AE_SUCCESS );
173 1608 : }
174 :
175 8038101 : Nonce::Nonce( uint64_t val )
176 : {
177 8038101 : uint64_t val_net = htobe64( val );
178 :
179 8038101 : memset( bytes, 0, 4 );
180 8038101 : memcpy( bytes + 4, &val_net, 8 );
181 8038101 : }
182 :
183 8076106 : uint64_t Nonce::val( void ) const
184 : {
185 8076106 : uint64_t ret;
186 8076106 : memcpy( &ret, bytes + 4, 8 );
187 8076106 : return be64toh( ret );
188 : }
189 :
190 40066 : Nonce::Nonce( const char *s_bytes, size_t len )
191 : {
192 40066 : if ( len != 8 ) {
193 0 : throw CryptoException( "Nonce representation must be 8 octets long." );
194 : }
195 :
196 40066 : memset( bytes, 0, 4 );
197 40066 : memcpy( bytes + 4, s_bytes, 8 );
198 40066 : }
199 :
200 38101 : const string Session::encrypt( const Message & plaintext )
201 : {
202 38101 : const size_t pt_len = plaintext.text.size();
203 38101 : const int ciphertext_len = pt_len + 16;
204 :
205 38101 : assert( (size_t)ciphertext_len <= ciphertext_buffer.len() );
206 38101 : assert( pt_len <= plaintext_buffer.len() );
207 :
208 38101 : memcpy( plaintext_buffer.data(), plaintext.text.data(), pt_len );
209 38101 : memcpy( nonce_buffer.data(), plaintext.nonce.data(), Nonce::NONCE_LEN );
210 :
211 38101 : if ( ciphertext_len != ae_encrypt( ctx, /* ctx */
212 38101 : nonce_buffer.data(), /* nonce */
213 38101 : plaintext_buffer.data(), /* pt */
214 : pt_len, /* pt_len */
215 : NULL, /* ad */
216 : 0, /* ad_len */
217 38101 : ciphertext_buffer.data(), /* ct */
218 : NULL, /* tag */
219 : AE_FINALIZE ) ) { /* final */
220 0 : throw CryptoException( "ae_encrypt() returned error." );
221 : }
222 :
223 38101 : blocks_encrypted += pt_len >> 4;
224 38101 : if ( pt_len & 0xF ) {
225 : /* partial block */
226 35615 : blocks_encrypted++;
227 : }
228 :
229 : /* "Both the privacy and the authenticity properties of OCB degrade as
230 : per s^2 / 2^128, where s is the total number of blocks that the
231 : adversary acquires.... In order to ensure that s^2 / 2^128 remains
232 : small, a given key should be used to encrypt at most 2^48 blocks (2^55
233 : bits or 4 petabytes)"
234 :
235 : -- http://tools.ietf.org/html/draft-krovetz-ocb-03
236 :
237 : We deem it unlikely that a legitimate user will send 4 PB through a Mosh
238 : session. If it happens, we simply kill the session. The server and
239 : client use the same key, so we actually need to die after 2^47 blocks.
240 : */
241 38101 : if ( blocks_encrypted >> 47 ) {
242 0 : throw CryptoException( "Encrypted 2^47 blocks.", true );
243 : }
244 :
245 38101 : string text( ciphertext_buffer.data(), ciphertext_len );
246 :
247 114303 : return plaintext.nonce.cc_str() + text;
248 38101 : }
249 :
250 40086 : const Message Session::decrypt( const char *str, size_t len )
251 : {
252 40086 : if ( len < 24 ) {
253 40 : throw CryptoException( "Ciphertext must contain nonce and tag." );
254 : }
255 :
256 40066 : int body_len = len - 8;
257 40066 : int pt_len = body_len - 16;
258 :
259 40066 : if ( pt_len < 0 ) { /* super-assertion that pt_len does not equal AE_INVALID */
260 0 : fprintf( stderr, "BUG.\n" );
261 0 : exit( 1 );
262 : }
263 :
264 40066 : assert( (size_t)body_len <= ciphertext_buffer.len() );
265 40066 : assert( (size_t)pt_len <= plaintext_buffer.len() );
266 :
267 40066 : Nonce nonce( str, 8 );
268 40066 : memcpy( ciphertext_buffer.data(), str + 8, body_len );
269 40066 : memcpy( nonce_buffer.data(), nonce.data(), Nonce::NONCE_LEN );
270 :
271 40066 : if ( pt_len != ae_decrypt( ctx, /* ctx */
272 40066 : nonce_buffer.data(), /* nonce */
273 40066 : ciphertext_buffer.data(), /* ct */
274 : body_len, /* ct_len */
275 : NULL, /* ad */
276 : 0, /* ad_len */
277 40066 : plaintext_buffer.data(), /* pt */
278 : NULL, /* tag */
279 : AE_FINALIZE ) ) { /* final */
280 4026 : throw CryptoException( "Packet failed integrity check." );
281 : }
282 :
283 38053 : const Message ret( nonce, string( plaintext_buffer.data(), pt_len ) );
284 :
285 38053 : return ret;
286 : }
287 :
288 : static rlim_t saved_core_rlimit;
289 :
290 : /* Disable dumping core, as a precaution to avoid saving sensitive data
291 : to disk. */
292 1352 : void Crypto::disable_dumping_core( void ) {
293 1352 : struct rlimit limit;
294 1352 : if ( 0 != getrlimit( RLIMIT_CORE, &limit ) ) {
295 : /* We don't throw CryptoException because this is called very early
296 : in main(), outside of 'try'. */
297 0 : perror( "getrlimit(RLIMIT_CORE)" );
298 0 : exit( 1 );
299 : }
300 :
301 1352 : saved_core_rlimit = limit.rlim_cur;
302 1352 : limit.rlim_cur = 0;
303 1352 : if ( 0 != setrlimit( RLIMIT_CORE, &limit ) ) {
304 0 : perror( "setrlimit(RLIMIT_CORE)" );
305 0 : exit( 1 );
306 : }
307 1352 : }
308 :
309 452 : void Crypto::reenable_dumping_core( void ) {
310 : /* Silent failure is safe. */
311 452 : struct rlimit limit;
312 452 : if ( 0 == getrlimit( RLIMIT_CORE, &limit ) ) {
313 452 : limit.rlim_cur = saved_core_rlimit;
314 452 : setrlimit( RLIMIT_CORE, &limit );
315 : }
316 452 : }
|