complete the rest of the ioctl api; add respective options to cmd

This commit is contained in:
J. Lowell Wofford 2020-12-01 11:10:26 -07:00
parent b8d0c20efe
commit 5386961c69
5 changed files with 110 additions and 15 deletions

View File

@ -2,6 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"os"
"strconv"
@ -14,8 +15,15 @@ Usage: %s <command> [<opts>...]
Commands:
get(entropy) - get the current system entropy.
addto(entcnt) <num> - Add <num> to the current entropy count (must be root).
get(entropy) - get the current system entropy.
addto(entcnt) <num> - (superuser) Add <num> bits to the current entropy count.
Note: this does not literally increase entropy count by <num>. The kernel adds using an asymptotic algorithm.
See <drivers/char/random.c> for details.
add(entropy) <file> [<quality>] - (superuser) Add the contents of <file> to entropy, incrementing entropy by the byte-length of the file.
The optional <quality> specifies the percentage of total data to count as Shannon entropy (default: 1, which is highly unlikely).
zap(entcnt) - (superuser) Clear the kernel entropy count.
clear(pool) - (superuser) Clear the entropy pool and counters (on modern linux, this just does zapentcnt).
reseed(crng) - (superuser) Reseed the CRNG.
`, os.Args[0])
}
@ -60,6 +68,37 @@ func main() {
if err = entropy.AddToEntCnt(add); err != nil {
fatal("entropy addition failed: %v", err)
}
case "add":
fallthrough
case "addentropy":
if len(os.Args) != 3 {
usageFatal("addtoentcnt requires a file path as an option")
}
var buf []byte
if buf, err = ioutil.ReadFile(os.Args[2]); err != nil {
fatal("could not read file %s: %v", os.Args[2], err)
}
if err = entropy.AddEntropy(len(buf), buf); err != nil {
fatal("failed to add entropy: %v", err)
}
case "zap":
fallthrough
case "zapentcnt":
if err = entropy.ZapEntCnt(); err != nil {
fatal("failed to zap entropy count: %v", err)
}
case "clear":
fallthrough
case "clearpool":
if err = entropy.ClearPool(); err != nil {
fatal("failed to clear entropy pool: %v", err)
}
case "reseed":
fallthrough
case "reseedcrng":
if err = entropy.ReseedCrng(); err != nil {
fatal("failed to reseed CRNG: %v", err)
}
case "help":
fallthrough
case "usage":

View File

@ -0,0 +1,5 @@
package entropy
import "encoding/binary"
var hbo = binary.LittleEndian

View File

@ -0,0 +1,5 @@
package entropy
import "encoding/binary"
var hbo = binary.LittleEndian

View File

@ -7,3 +7,19 @@ func GetEntCnt() (int, error) {
func AddToEntCnt(add int) error {
return addToEntCnt(add)
}
func AddEntropy(cnt int, buf []byte) error {
return addEntropy(cnt, buf)
}
func ZapEntCnt() error {
return zapEntCnt()
}
func ClearPool() error {
return clearPool()
}
func ReseedCrng() error {
return reseedCrng()
}

View File

@ -8,7 +8,7 @@ import (
"golang.org/x/sys/unix"
)
var entropy_device = "/dev/urandom"
var entropy_device = "/dev/random"
func entropyIoctl(request int, data uintptr) (err error) {
var fd int
@ -35,21 +35,51 @@ func addToEntCnt(add int) (err error) {
return entropyIoctl(RNDADDTOENTCNT, uintptr(unsafe.Pointer(&add)))
}
func addToEntropy() {
/* IOCTL argument structure
struct rand_pool_info {
int entropy_count;
int buf_size;
__u32 buf[0];
};
*/
type randPoolInfo struct {
entropyCount int
bufSize int
buf uint32 // first 4 bytes, followed by the rest
}
func addEntropy() {
/* IOCTL argument structure
struct rand_pool_info {
int entropy_count;
int buf_size;
__u32 buf[0];
};
*/
func addEntropy(cnt int, buf []byte) (err error) {
blen := len(buf)
// we need to pad to 4-byte chunks since this is a uint32 array
if blen%4 != 0 {
for i := 0; i < 4-(blen%4); i++ {
buf = append(buf, 0x00)
}
}
blen = len(buf)
// make a byte slice and pack it
// this may not be the cleanest way to do this...
const structSize = int(unsafe.Sizeof(randPoolInfo{}))
rpi := make([]byte, structSize+blen-1)
hbo.PutUint32(rpi[0:], uint32(cnt))
hbo.PutUint32(rpi[4:], uint32(blen))
copy(rpi[8:], buf)
err = entropyIoctl(RNDADDENTROPY, uintptr(unsafe.Pointer(&rpi[0])))
return
}
func clearPool() {
func zapEntCnt() (err error) {
return entropyIoctl(RNDZAPENTCNT, uintptr(unsafe.Pointer(nil)))
}
func clearPool() (err error) {
return entropyIoctl(RNDCLEARPOOL, uintptr(unsafe.Pointer(nil)))
}
func reseedCrng() (err error) {
return entropyIoctl(RNDRESEEDCRNG, uintptr(unsafe.Pointer(nil)))
}