Browse Source

[netdevice] Use link-layer address as part of RNG seed

iPXE currently seeds the random number generator using the system
timer tick count.  When large numbers of machines are booted
simultaneously, multiple machines may end up choosing the same DHCP
transaction ID (XID) value; this can cause problems.

Fix by using the least significant (and hence most variable) bits of
each network device's link-layer address to perturb the random number
generator.  This introduces some per-machine unique data into the
random number generator's seed, and so reduces the chances of DHCP XID
collisions.

This does not affect the ANS X9.82-compatible random bit generator
used by TLS and other cryptography code, which uses an entirely
separate source of entropy.

Originally-implemented-by: Bernhard Kohl <bernhard.kohl@nsn.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
445ac9fbdc
1 changed files with 11 additions and 2 deletions
  1. 11
    2
      src/net/netdevice.c

+ 11
- 2
src/net/netdevice.c View File

442
  */
442
  */
443
 int register_netdev ( struct net_device *netdev ) {
443
 int register_netdev ( struct net_device *netdev ) {
444
 	static unsigned int ifindex = 0;
444
 	static unsigned int ifindex = 0;
445
+	struct ll_protocol *ll_protocol = netdev->ll_protocol;
445
 	struct net_driver *driver;
446
 	struct net_driver *driver;
447
+	uint32_t seed;
446
 	int rc;
448
 	int rc;
447
 
449
 
448
 	/* Create device name */
450
 	/* Create device name */
453
 
455
 
454
 	/* Set initial link-layer address, if not already set */
456
 	/* Set initial link-layer address, if not already set */
455
 	if ( ! netdev_has_ll_addr ( netdev ) ) {
457
 	if ( ! netdev_has_ll_addr ( netdev ) ) {
456
-		netdev->ll_protocol->init_addr ( netdev->hw_addr,
457
-						 netdev->ll_addr );
458
+		ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
458
 	}
459
 	}
459
 
460
 
461
+	/* Use least significant bits of the link-layer address to
462
+	 * improve the randomness of the (non-cryptographic) random
463
+	 * number generator.
464
+	 */
465
+	memcpy ( &seed, ( netdev->ll_addr + ll_protocol->ll_addr_len
466
+			  - sizeof ( seed ) ), sizeof ( seed ) );
467
+	srand ( rand() ^ seed );
468
+
460
 	/* Add to device list */
469
 	/* Add to device list */
461
 	netdev_get ( netdev );
470
 	netdev_get ( netdev );
462
 	list_add_tail ( &netdev->list, &net_devices );
471
 	list_add_tail ( &netdev->list, &net_devices );

Loading…
Cancel
Save