1Secure Framework 2================ 3 4This layer provides wrappers around sendto(2) and recvfrom(2), the 5secure versions expect an additional 'struct security_association *sa'. 6 7The security association describes the encryption/authentication and 8decryption/validation functions that are used to provide confidentiality 9and integrity for sent messages. 10 11The implementation heavily draws on the following IPsec related RFCs, 12 13 RFC 2401 -- Security Architecture for the Internet Protocol 14 RFC 2406 -- IP Encapsulating Security Payload (ESP) 15 RFC 3948 -- UDP Encapsulation of IPsec ESP Packets 16 17The main difference is that in our case the security layer does not work 18between a pair of hosts, but assists the application to create secure 19tunnels between (logical) application level endpoints. Unlike IPsec, our 20payload does not include the TCP or UDP, and IP headers. 21 22Similar to IPsec, this layer does not implement any key exchange and 23setup, that step is left up to the application. 24 25Here is a short description of the important structures and functions, 26 27 struct security_association { 28 /* incoming packets */ 29 30 /* identifier to match an incoming packet with the the correct 31 * logical connection. Really only here for the convenience of 32 * the application, it is not used by secure_recvfrom. 33 * Security identifiers < 256 are considered 'reserved', see 34 * secure_sendto/secure_recvfrom */ 35 uint32_t recv_spi; 36 37 /* The following are used for to detect replay attacks and 38 * should be initialized to 0 */ 39 uint32_t recv_seq; 40 unsigned long recv_win; 41 42 /* function descriptor and state for packet validation */ 43 const struct secure_auth *validate; 44 void *validate_context; 45 46 /* function descriptor and state for decryption */ 47 const struct secure_encr *decrypt; 48 void *decrypt_context; 49 50 /* outgoing packets */ 51 /* remote connection identifier */ 52 uint32_t peer_spi; 53 54 /* sequence number used for outgoing packets, should be 55 * initialized to 0 */ 56 uint32_t peer_seq; 57 58 /* trusted address of the peer, outgoing encrypted packets will 59 * be sent to this address, incoming packets that are correctly 60 * validated will update this address */ 61 struct sockaddr_storage peer; 62 socklen_t peerlen; 63 64 /* initialization vector/counter, should be initialized to a 65 * random value, secure_sendto will properly increment it */ 66 uint8_t send_iv[MAXIVLEN]; 67 68 /* function descriptor and context for encryption */ 69 const struct secure_encr *encrypt; 70 void *encrypt_context; 71 72 /* function descriptor and context for packet authentication */ 73 const struct secure_auth *authenticate; 74 void *authenticate_context; 75 }; 76 77This structure contains all the information required to securely send 78and receive encrypted and authenticated packets. 79 80 81 ssize_t secure_recvfrom(int s, void *buf, size_t len, int flags, 82 struct sockaddr *peer, socklen_t *peerlen, 83 struct security_association **sa, 84 struct security_association *(*GETSA)(uint32_t spi)) 85 86Wrapper around recvfrom to decrypt/validate incoming packets. If the 87packet is smaller than 8 bytes, or the first big-endian 32-bit word is 88less than 256, the packet is considered unencrypted and passed through 89without any futher processing. 90 91Otherwise, the GETSA callback is called with the 32-bit identifier (in 92native byte order). If GETSA returns NULL, the packet is dropped and we 93return EAGAIN which is (in Linux) identical to a received packet with a 94bad UDP checksum. 95 96If GETSA did return a valid security association, 97 - the sequence number is checked (anti-replay) 98 - we validate the message checksum 99 - update the receive window and sa->peer 100 - decrypt the packet 101 - check the padding 102 103If any of these steps fail, the packet is dropped and EAGAIN is 104returned. 'peer' is set whenever the packet is received, but sa->peer 105is only updated when the packet has been successfully validated. 106 107 108 ssize_t secure_sendto(int s, const void *buf, size_t len, int flags, 109 const struct sockaddr *to, socklen_t tolen, 110 struct security_association *sa) 111 112Send a packet securely. If sa is NULL or does not have an encryption and 113authentication function defined, and the first 32-bit big-endian word in 114buf is less than 256 then the data in 'buf' is sent as-is to the address 115specified by the 'to' argument. The check if the value is less than 256 116is to make sure the packet does not get interpreted by the receiver side 117as a valid encrypted packet. 118 119If we do have a valid security association, the payload is padded, 120encrypted and authenticated. The result is sent to the address in 121sa->peer (i.e. NOT to the 'to' address). 122 123Implemented authentication and encryption modes 124=============================================== 125 126The framework is pretty flexible and should be able to support many 127encryption and authentication algorithms, however the provided ones are 128all based on the AES block cipher. 129 130AES-XCBC-MAC-96 authentication 131============================== 132 133 RFC 3566 -- The AES-XCBC-MAC-96 Algorithm and Its Use With IPsec 134 135AES-CBC based message integrity checksum, requires a 128-bit (16-byte) 136key and adds 12 checksum bytes to the packet. 137 138 139AES-CBC encryption 140================== 141 142 NIST Special Publication 800-38A -- Recommendation for Block Cipher 143 Modes of Operation 144 RFC 3602 -- The AES-CBC Cipher Algorithm and Its Use with IPsec 145 146This is a pretty straightforward and well understood cipher block 147chaining mode using AES as the encryption algorithm. CBC encryption 148requires the initialization vector to be the same size as the encryption 149block (which is 16-bytes for AES) The initialization vector has to be 150unpredictable, so we encrypt the IV-counter that was set up by the 151generic code in secure_sendto to obtain a pseudo random sequence. 152 153Can be used with 128, 192, and 256 bit keys (16, 24, and 32 bytes). 154 155 156AES-CCM encryption 157================== 158 159 NIST Special Publication 800-38C -- Recommendation for Block Cipher 160 Modes of Operation: The CCM Mode for 161 Authentication and Confidentiality 162 RFC 4309 -- Using Advanced Encryption Standard (AES) CCM Mode with 163 IPsec Encapsulating Security Payload (ESP) 164 165This is a combined encryption and authentication algorithm, so we do not 166need a separate authentication function. It also only needs 8 bytes for 167the initialization vector. The checksum can be either 8, 12, or 16 168bytes. As a result this algorithm has a lower per packet overhead, only 169between 16 and 24 bytes instead of the 28 bytes we need for AES-CBC with 170AES-XCBC-MAC-96. 171 172We also need less key material because we do not need a separate key for 173the message authentication algorithm. Finally, this algorithm lends 174itself well for several optimizations, it only uses the AES encrypt 175operation, initializing the encryption stream can be done off-line 176by the sender before the packet has be be sent and it is highly 177parallelizable. 178 179This encryption mode uses 152, 206, or 280-bits of key material 180(19, 27, or 35 bytes). 181 182Although there are several advantages, there is one pretty significant 183disadvantage. When a combination of the same key and initialization 184vector is reused at any time it becomes a trivial operation to obtain 185the plaintext of both messages. As such it is not recommended to use 186this encryption mode when we have static keys, such as during the 187initial handshake (user passwords, the keys in a Coda token, etc). 188 189 190AES implementation 191================== 192 193The used AES implementation is the Rijndael reference implementation (v3.0). 194I picked this because it seems to be fairly portable ANSI-C and we do not have 195to deal with trying to teach automake/autoconf about various platform specific 196assembly implementations and they pose no licensing conflicts wrt. to RPC2's 197LGPL license. 198 199As an alternative there is also the very small implementation by Mike Scott, 200however that code relies on global variables for the encryption/decryption 201state, only supports in-place operations and uses fairly generic naming. So it 202could use a bit of cleaning up so that the context can be passed avoid 203name-clashes. 204 205To make it simply to replace the AES implementation, the remaining code 206expects to be able to include "aes.h", which defines 5 functions to 207initialize, setup keys and to encrypt/decrypt a single block. 208 209There are several alternative implementation that can be used, 210 211- A more optimized implementation by Dr. Brian Gladman, his code is dual 212 licensed as BSD with an advertising clause, or alternatively pure GPL. 213 Neither of these mix well with RPC2's LGPL license so we probably can't 214 distribute binaries that are linked using his code. If you really need the 215 extra performance and make sure you comply with his license terms (as this 216 code is LGPL that would be the BSD license + advertising clause) and provide 217 the required copyright notice and disclaimer in any documentation and/or 218 associated materials that you distribute, you can find his version at, 219 220 http://fp.gladman.plus.com/AES/index.htm 221 222- There is also a modified version of the rijndael v3.0 reference code 223 available as part of the wpa_supplicant sources. It can optionally use 224 smaller tables which make the code 8KB smaller, and possibly make the code 225 less vulnerable to timing attacks, however it only supports 128-bit keys. 226 The modification are by Jouni Malinen and it seems to be dual licensed as 227 BSD without advertising clause or GPL, 228 229 http://hostap.epitest.fi/wpa_supplicant/ 230 231- There are more, but from what I've seen most implementations are based on, 232 233 * original NIST submission (aka. rijndael v2.2 reference implementation), 234 * The optimized/cleaned-up Rijndael v3.0 reference implementation, 235 * Mike Scott's code, when the requirements tend to favour small size, 236 * Brian Gladman's code, when the requirements are mostly performance. 237 238- If you feel brave you can implement your own, the following is an excellent 239 article that explains a lot of the implementations details, 240 241 http://msdn.microsoft.com/msdnmag/issues/03/11/AES/ 242 243 244AES testvectors 245=============== 246 247testvectors.h contains several AES testvectors from 248 249 http://csrc.nist.gov/CryptoToolkit/aes/rijndael/rijndael-vals.zip 250 251If you want to regenerate or expand the number of tests that are run 252during initialization, unzip the testvalues in a subdirectory named 253'testvalues' and run gen_testvectors.sh to rebuild. At the top of the 254script are some comments and possible settings to vary the memory 255overhead/execution time to run these tests. 256 257We run the complete set of included test vectors during every startup. 258It only adds a delay of about 0.43 seconds on a 600MHz PIII, and less 259than 0.07 seconds on a 3.2GHz P4. But the delay does add a tiny amount 260of non-deterministic entropy for the PRNG initialization. 261 262 263PRNG implementation 264=================== 265 266A deterministic pseudo random number generator based on ANSI X9.31, with 267the NIST recommended usage for using AES as a mixing function. The 268algorithm is fairly close to CBC mode encryption. 269 270There is a 16-byte pool of random data that we use as the IV. Then when 271we want to get random data we generate an initial seed based on the 272current timestamp, some uninitialized data from the stack, and a counter. 273 274This block is then encrypted using AES-CBC where the pool is used as the 275IV. This results in a block of 16-bytes of random data. The random block 276is then xor-ed with the original seed to get the next block of seed 277data. We then refresh the pool of random data by encrypting the seed 278block. These steps are repeated until we've returned the number of 279random bytes that were requested. 280 281To initialize the pool of random data and the AES128 encryption key, we 282get the current timestamp, and read random data from /dev/random (or 283/dev/urandom). When /dev/random is unavailable we fall back on several 284lower entropy sources such as times(), getpid(), and libc's random(). 285 286The first block of random data is discarded, and we run a couple of 287statistical tests to see if the resulting random data actually looks 288reasonable. Passing these tests does not guarantee that the generated 289random numbers are cryptographically strong, but it should detect 290serious breakage. 291 292 293RPC2 secure handshake 294===================== 295 296The modified RPC2 handshake is based on the analysis and proposed 297implementation of the Andrew Secure RPC Handshake in 'A Logic of 298Authentication', by Michael Burrows, Martin Abadi, and Roger Needham. 299 300The handshake uses 4 steps so set up separate server->client and 301client->server encryption and authentication keys. 302 303 1. client -> server: Na, A 304 305 this is a normal RPC2 INIT1 packet, but with the RPC2SEC_CAPABLE 306 flag set in a header field. Na is a nonce which is used to avoid 307 replay attacks. A is the client identifier, it can be a username 308 or an encrypted Coda token. 309 310 2. server -> client: {Na, K'ab}Kab 311 312 The server sends back the nonce and a random key which will be used 313 for client -> server traffic encrypted with the shared secret that 314 was obtained from the client identifier. The client knows this is in 315 response to it's INIT1 packet because of the value of the nonce. 316 317 This packet is encrypted with AES-CBC and authenticated with 318 AES-XCBC-MAC-96 319 320 3. client -> server: {Na, K'ba}K'ab 321 322 The client responds with the nonce and a random key that will be 323 used for any further server -> client traffic, this is encrypted and 324 authenticated with the random session key we received in step 2. 325 326 The packet is encrypted with the encryption algorithm that server 327 chose and sent in step 2 along with the key. Currently this is 328 AES-CCM8. 329 330 4. server -> client: {Na, Nb}K'ba 331 332 The server sends back the nonce and an initial sequence number (Nb) 333 encrypted with the session key and algorithm it received from the 334 client in step 3. 335 336