linux: add proc_boot_id()
A new helper for the util.linux module which exposes the linux boot-id. For security reasons, the boot-id is never exposed directly, but instead only exposed through an application-id combined with the boot-id via HMAC-SHA256. Note that a raw kernel boot-id is always considered confidential, since we never want an outside entity to deduce any information when they see a boot-id used in protocol A and one in protocol B. It should not be possible to tell whether both are from the same user and boot or not. Hence, both should use their own boot-id namespace.
This commit is contained in:
parent
aefaf21411
commit
ebbedd1e89
2 changed files with 56 additions and 0 deletions
|
|
@ -16,15 +16,19 @@ import array
|
||||||
import ctypes
|
import ctypes
|
||||||
import ctypes.util
|
import ctypes.util
|
||||||
import fcntl
|
import fcntl
|
||||||
|
import hashlib
|
||||||
|
import hmac
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import struct
|
import struct
|
||||||
import threading
|
import threading
|
||||||
|
import uuid
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"fcntl_flock",
|
"fcntl_flock",
|
||||||
"ioctl_get_immutable",
|
"ioctl_get_immutable",
|
||||||
"ioctl_toggle_immutable",
|
"ioctl_toggle_immutable",
|
||||||
|
"proc_boot_id",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -415,3 +419,37 @@ def fcntl_flock(fd: int, lock_type: int, wait: bool = False):
|
||||||
#
|
#
|
||||||
|
|
||||||
fcntl.fcntl(fd, lock_cmd, arg_flock64)
|
fcntl.fcntl(fd, lock_cmd, arg_flock64)
|
||||||
|
|
||||||
|
|
||||||
|
def proc_boot_id(appid: str):
|
||||||
|
"""Acquire Application-specific Boot-ID
|
||||||
|
|
||||||
|
This queries the kernel for the boot-id of the running system. It then
|
||||||
|
calculates an application-specific boot-id by combining the kernel boot-id
|
||||||
|
with the provided application-id. This uses a cryptographic HMAC.
|
||||||
|
Therefore, the kernel boot-id will not be deducable from the output. This
|
||||||
|
allows the caller to use the resulting application specific boot-id for any
|
||||||
|
purpose they wish without exposing the confidential kernel boot-id.
|
||||||
|
|
||||||
|
This always returns an object of type `uuid.UUID` from the python standard
|
||||||
|
library. Furthermore, this always produces UUIDs of version 4 variant 1.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
appid
|
||||||
|
An arbitrary object (usually a string) that identifies the use-case of
|
||||||
|
the boot-id.
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open("/proc/sys/kernel/random/boot_id", "r", encoding="utf8") as f:
|
||||||
|
content = f.read().strip(" \t\r\n")
|
||||||
|
|
||||||
|
# Running the boot-id through HMAC-SHA256 guarantees that the original
|
||||||
|
# boot-id will not be exposed. Thus two IDs generated with this interface
|
||||||
|
# will not allow to deduce whether they share a common boot-id.
|
||||||
|
# From the result, we throw away everything but the lower 128bits and then
|
||||||
|
# turn it into a UUID version 4 variant 1.
|
||||||
|
h = bytearray(hmac.new(content.encode(), appid.encode(), hashlib.sha256).digest()) # type: ignore
|
||||||
|
h[6] = (h[6] & 0x0f) | 0x40 # mark as version 4
|
||||||
|
h[8] = (h[6] & 0x3f) | 0x80 # mark as variant 1
|
||||||
|
return uuid.UUID(bytes=bytes(h[0:16]))
|
||||||
|
|
|
||||||
|
|
@ -165,3 +165,21 @@ def test_fcntl_flock():
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
os.close(fd2)
|
os.close(fd2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_proc_boot_id():
|
||||||
|
#
|
||||||
|
# Test the `proc_boot_id()` function which reads the current boot-id
|
||||||
|
# from the kernel. Make sure it is a valid UUID and also consistent on
|
||||||
|
# repeated queries.
|
||||||
|
#
|
||||||
|
|
||||||
|
bootid = linux.proc_boot_id("test")
|
||||||
|
assert len(bootid.hex) == 32
|
||||||
|
assert bootid.version == 4
|
||||||
|
|
||||||
|
bootid2 = linux.proc_boot_id("test")
|
||||||
|
assert bootid.int == bootid2.int
|
||||||
|
|
||||||
|
bootid3 = linux.proc_boot_id("foobar")
|
||||||
|
assert bootid.int != bootid3.int
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue