From 49b3026574ab692cfabcabe90751b163a76df31b Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Thu, 2 Mar 2017 11:58:07 -0800 Subject: crypto: add secure random reader using getrandom This commit adds in RandReader, a cryptographically secure io.Reader that will fail when the os has insufficient randomness. This is done using the getrandom() syscall in non-blocking mode. see: http://man7.org/linux/man-pages/man2/getrandom.2.html Any kernel new enough to have filesystem encryption will also have this syscall. This RandReader is preferable to the one provided by the standard library in crypto/rand. See the bugs: https://github.com/golang/go/issues/11833 https://github.com/golang/go/issues/19274 This will be removed when go updates the crypto/rand implementation. Change-Id: Icccaf07bc6011b95cd31a5c268e7486807dcffe2 --- crypto/rand.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 crypto/rand.go (limited to 'crypto/rand.go') diff --git a/crypto/rand.go b/crypto/rand.go new file mode 100644 index 0000000..d9d4cff --- /dev/null +++ b/crypto/rand.go @@ -0,0 +1,62 @@ +/* + * rand.go - Reader used to generate secure random data for fscrypt. + * + * Copyright 2017 Google Inc. + * Author: Joe Richey (joerichey@google.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package crypto + +import ( + "io" + + "golang.org/x/sys/unix" + + "fscrypt/util" +) + +/* +RandReader uses the Linux Getrandom() syscall to read random bytes. If the +operating system has insufficient randomness, the read will fail. This is an +improvement over Go's built-in crypto/rand which will still return bytes if the +system has insufficiency entropy (https://github.com/golang/go/issues/19274). + +While this syscall was only introduced in Kernel v3.17, it predates the +introduction of filesystem encryption, so it introduces no additional +compatibility issues. +*/ +var RandReader io.Reader = randReader{} + +// As we just call into Getrandom, no internal data is needed. +type randReader struct{} + +func (r randReader) Read(buffer []byte) (int, error) { + n, err := unix.Getrandom(buffer, unix.GRND_NONBLOCK) + switch err { + case nil: + return n, nil + case unix.EAGAIN: + return 0, util.SystemErrorF("entropy pool not yet initialized") + case unix.ENOSYS: + return 0, util.SystemErrorF("getrandom not implemented; kernel must be v3.17 or later") + default: + return 0, util.SystemErrorF("cannot get randomness: %v", err) + } +} + +// NewRandomKey creates a random key (from RandReader) of the specified length. +func NewRandomKey(length int) (*Key, error) { + return NewFixedLengthKeyFromReader(RandReader, length) +} -- cgit v1.2.3