diff options
| author | Joe Richey <joerichey@google.com> | 2017-03-02 11:58:07 -0800 |
|---|---|---|
| committer | Joe Richey joerichey@google.com <joerichey@google.com> | 2017-05-02 13:39:18 -0700 |
| commit | 49b3026574ab692cfabcabe90751b163a76df31b (patch) | |
| tree | c638076dd5faeadf84afd49fcf15728f68181eba /crypto/rand.go | |
| parent | 53d15f466a665e4e564af3afdcbcfe9ff1c91331 (diff) | |
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
Diffstat (limited to 'crypto/rand.go')
| -rw-r--r-- | crypto/rand.go | 62 |
1 files changed, 62 insertions, 0 deletions
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) +} |