diff options
| author | David S. Miller <davem@davemloft.net> | 2011-08-03 23:50:44 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-08-06 21:33:19 -0400 |
| commit | 6e5714eaf77d79ae1c8b47e3e040ff5411b717ec (patch) | |
| tree | 30bd0d7a6a0a6ff0ace6da1835ae7b7167cce5e4 | |
| parent | bc0b96b54a21246e377122d54569eef71cec535f (diff) | |
net: Compute protocol sequence numbers and fragment IDs using MD5.
Computers have become a lot faster since we compromised on the
partial MD4 hash which we use currently for performance reasons.
MD5 is a much safer choice, and is inline with both RFC1948 and
other ISS generators (OpenBSD, Solaris, etc.)
Furthermore, only having 24-bits of the sequence number be truly
unpredictable is a very serious limitation. So the periodic
regeneration and 8-bit counter have been removed. We compute and
use a full 32-bit sequence number.
For ipv6, DCCP was found to use a 32-bit truncated initial sequence
number (it needs 43-bits) and that is fixed here as well.
Reported-by: Dan Kaminsky <dan@doxpara.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/char/random.c | 349 | ||||
| -rw-r--r-- | include/linux/random.h | 12 | ||||
| -rw-r--r-- | include/net/secure_seq.h | 20 | ||||
| -rw-r--r-- | net/core/Makefile | 2 | ||||
| -rw-r--r-- | net/core/secure_seq.c | 184 | ||||
| -rw-r--r-- | net/dccp/ipv4.c | 1 | ||||
| -rw-r--r-- | net/dccp/ipv6.c | 9 | ||||
| -rw-r--r-- | net/ipv4/inet_hashtables.c | 1 | ||||
| -rw-r--r-- | net/ipv4/inetpeer.c | 1 | ||||
| -rw-r--r-- | net/ipv4/netfilter/nf_nat_proto_common.c | 1 | ||||
| -rw-r--r-- | net/ipv4/route.c | 1 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 1 | ||||
| -rw-r--r-- | net/ipv6/inet6_hashtables.c | 1 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 1 |
14 files changed, 223 insertions, 361 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index 729281961f22..c35a785005b0 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -1300,345 +1300,14 @@ ctl_table random_table[] = { | |||
| 1300 | }; | 1300 | }; |
| 1301 | #endif /* CONFIG_SYSCTL */ | 1301 | #endif /* CONFIG_SYSCTL */ |
| 1302 | 1302 | ||
| 1303 | /******************************************************************** | 1303 | static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; |
| 1304 | * | ||
| 1305 | * Random functions for networking | ||
| 1306 | * | ||
| 1307 | ********************************************************************/ | ||
| 1308 | |||
| 1309 | /* | ||
| 1310 | * TCP initial sequence number picking. This uses the random number | ||
| 1311 | * generator to pick an initial secret value. This value is hashed | ||
| 1312 | * along with the TCP endpoint information to provide a unique | ||
| 1313 | * starting point for each pair of TCP endpoints. This defeats | ||
| 1314 | * attacks which rely on guessing the initial TCP sequence number. | ||
| 1315 | * This algorithm was suggested by Steve Bellovin. | ||
| 1316 | * | ||
| 1317 | * Using a very strong hash was taking an appreciable amount of the total | ||
| 1318 | * TCP connection establishment time, so this is a weaker hash, | ||
| 1319 | * compensated for by changing the secret periodically. | ||
| 1320 | */ | ||
| 1321 | |||
| 1322 | /* F, G and H are basic MD4 functions: selection, majority, parity */ | ||
| 1323 | #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) | ||
| 1324 | #define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) | ||
| 1325 | #define H(x, y, z) ((x) ^ (y) ^ (z)) | ||
| 1326 | |||
| 1327 | /* | ||
| 1328 | * The generic round function. The application is so specific that | ||
| 1329 | * we don't bother protecting all the arguments with parens, as is generally | ||
| 1330 | * good macro practice, in favor of extra legibility. | ||
| 1331 | * Rotation is separate from addition to prevent recomputation | ||
| 1332 | */ | ||
| 1333 | #define ROUND(f, a, b, c, d, x, s) \ | ||
| 1334 | (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s))) | ||
| 1335 | #define K1 0 | ||
| 1336 | #define K2 013240474631UL | ||
| 1337 | #define K3 015666365641UL | ||
| 1338 | |||
| 1339 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 1340 | |||
| 1341 | static __u32 twothirdsMD4Transform(__u32 const buf[4], __u32 const in[12]) | ||
| 1342 | { | ||
| 1343 | __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; | ||
| 1344 | |||
| 1345 | /* Round 1 */ | ||
| 1346 | ROUND(F, a, b, c, d, in[ 0] + K1, 3); | ||
| 1347 | ROUND(F, d, a, b, c, in[ 1] + K1, 7); | ||
| 1348 | ROUND(F, c, d, a, b, in[ 2] + K1, 11); | ||
| 1349 | ROUND(F, b, c, d, a, in[ 3] + K1, 19); | ||
| 1350 | ROUND(F, a, b, c, d, in[ 4] + K1, 3); | ||
| 1351 | ROUND(F, d, a, b, c, in[ 5] + K1, 7); | ||
| 1352 | ROUND(F, c, d, a, b, in[ 6] + K1, 11); | ||
| 1353 | ROUND(F, b, c, d, a, in[ 7] + K1, 19); | ||
| 1354 | ROUND(F, a, b, c, d, in[ 8] + K1, 3); | ||
| 1355 | ROUND(F, d, a, b, c, in[ 9] + K1, 7); | ||
| 1356 | ROUND(F, c, d, a, b, in[10] + K1, 11); | ||
| 1357 | ROUND(F, b, c, d, a, in[11] + K1, 19); | ||
| 1358 | |||
| 1359 | /* Round 2 */ | ||
| 1360 | ROUND(G, a, b, c, d, in[ 1] + K2, 3); | ||
| 1361 | ROUND(G, d, a, b, c, in[ 3] + K2, 5); | ||
| 1362 | ROUND(G, c, d, a, b, in[ 5] + K2, 9); | ||
| 1363 | ROUND(G, b, c, d, a, in[ 7] + K2, 13); | ||
| 1364 | ROUND(G, a, b, c, d, in[ 9] + K2, 3); | ||
| 1365 | ROUND(G, d, a, b, c, in[11] + K2, 5); | ||
| 1366 | ROUND(G, c, d, a, b, in[ 0] + K2, 9); | ||
| 1367 | ROUND(G, b, c, d, a, in[ 2] + K2, 13); | ||
| 1368 | ROUND(G, a, b, c, d, in[ 4] + K2, 3); | ||
| 1369 | ROUND(G, d, a, b, c, in[ 6] + K2, 5); | ||
| 1370 | ROUND(G, c, d, a, b, in[ 8] + K2, 9); | ||
| 1371 | ROUND(G, b, c, d, a, in[10] + K2, 13); | ||
| 1372 | |||
| 1373 | /* Round 3 */ | ||
| 1374 | ROUND(H, a, b, c, d, in[ 3] + K3, 3); | ||
| 1375 | ROUND(H, d, a, b, c, in[ 7] + K3, 9); | ||
| 1376 | ROUND(H, c, d, a, b, in[11] + K3, 11); | ||
| 1377 | ROUND(H, b, c, d, a, in[ 2] + K3, 15); | ||
| 1378 | ROUND(H, a, b, c, d, in[ 6] + K3, 3); | ||
| 1379 | ROUND(H, d, a, b, c, in[10] + K3, 9); | ||
| 1380 | ROUND(H, c, d, a, b, in[ 1] + K3, 11); | ||
| 1381 | ROUND(H, b, c, d, a, in[ 5] + K3, 15); | ||
| 1382 | ROUND(H, a, b, c, d, in[ 9] + K3, 3); | ||
| 1383 | ROUND(H, d, a, b, c, in[ 0] + K3, 9); | ||
| 1384 | ROUND(H, c, d, a, b, in[ 4] + K3, 11); | ||
| 1385 | ROUND(H, b, c, d, a, in[ 8] + K3, 15); | ||
| 1386 | |||
| 1387 | return buf[1] + b; /* "most hashed" word */ | ||
| 1388 | /* Alternative: return sum of all words? */ | ||
| 1389 | } | ||
| 1390 | #endif | ||
| 1391 | |||
| 1392 | #undef ROUND | ||
| 1393 | #undef F | ||
| 1394 | #undef G | ||
| 1395 | #undef H | ||
| 1396 | #undef K1 | ||
| 1397 | #undef K2 | ||
| 1398 | #undef K3 | ||
| 1399 | |||
| 1400 | /* This should not be decreased so low that ISNs wrap too fast. */ | ||
| 1401 | #define REKEY_INTERVAL (300 * HZ) | ||
| 1402 | /* | ||
| 1403 | * Bit layout of the tcp sequence numbers (before adding current time): | ||
| 1404 | * bit 24-31: increased after every key exchange | ||
| 1405 | * bit 0-23: hash(source,dest) | ||
| 1406 | * | ||
| 1407 | * The implementation is similar to the algorithm described | ||
| 1408 | * in the Appendix of RFC 1185, except that | ||
| 1409 | * - it uses a 1 MHz clock instead of a 250 kHz clock | ||
| 1410 | * - it performs a rekey every 5 minutes, which is equivalent | ||
| 1411 | * to a (source,dest) tulple dependent forward jump of the | ||
| 1412 | * clock by 0..2^(HASH_BITS+1) | ||
| 1413 | * | ||
| 1414 | * Thus the average ISN wraparound time is 68 minutes instead of | ||
| 1415 | * 4.55 hours. | ||
| 1416 | * | ||
| 1417 | * SMP cleanup and lock avoidance with poor man's RCU. | ||
| 1418 | * Manfred Spraul <manfred@colorfullife.com> | ||
| 1419 | * | ||
| 1420 | */ | ||
| 1421 | #define COUNT_BITS 8 | ||
| 1422 | #define COUNT_MASK ((1 << COUNT_BITS) - 1) | ||
| 1423 | #define HASH_BITS 24 | ||
| 1424 | #define HASH_MASK ((1 << HASH_BITS) - 1) | ||
| 1425 | 1304 | ||
| 1426 | static struct keydata { | 1305 | static int __init random_int_secret_init(void) |
| 1427 | __u32 count; /* already shifted to the final position */ | ||
| 1428 | __u32 secret[12]; | ||
| 1429 | } ____cacheline_aligned ip_keydata[2]; | ||
| 1430 | |||
| 1431 | static unsigned int ip_cnt; | ||
| 1432 | |||
| 1433 | static void rekey_seq_generator(struct work_struct *work); | ||
| 1434 | |||
| 1435 | static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator); | ||
| 1436 | |||
| 1437 | /* | ||
| 1438 | * Lock avoidance: | ||
| 1439 | * The ISN generation runs lockless - it's just a hash over random data. | ||
| 1440 | * State changes happen every 5 minutes when the random key is replaced. | ||
| 1441 | * Synchronization is performed by having two copies of the hash function | ||
| 1442 | * state and rekey_seq_generator always updates the inactive copy. | ||
| 1443 | * The copy is then activated by updating ip_cnt. | ||
| 1444 | * The implementation breaks down if someone blocks the thread | ||
| 1445 | * that processes SYN requests for more than 5 minutes. Should never | ||
| 1446 | * happen, and even if that happens only a not perfectly compliant | ||
| 1447 | * ISN is generated, nothing fatal. | ||
| 1448 | */ | ||
| 1449 | static void rekey_seq_generator(struct work_struct *work) | ||
| 1450 | { | 1306 | { |
| 1451 | struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)]; | 1307 | get_random_bytes(random_int_secret, sizeof(random_int_secret)); |
| 1452 | |||
| 1453 | get_random_bytes(keyptr->secret, sizeof(keyptr->secret)); | ||
| 1454 | keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS; | ||
| 1455 | smp_wmb(); | ||
| 1456 | ip_cnt++; | ||
| 1457 | schedule_delayed_work(&rekey_work, | ||
| 1458 | round_jiffies_relative(REKEY_INTERVAL)); | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | static inline struct keydata *get_keyptr(void) | ||
| 1462 | { | ||
| 1463 | struct keydata *keyptr = &ip_keydata[ip_cnt & 1]; | ||
| 1464 | |||
| 1465 | smp_rmb(); | ||
