mirror of
https://github.com/octoleo/restic.git
synced 2024-11-01 19:32:32 +00:00
6e1a3987b7
This commit adds a command called `self-update` which downloads the latest released version of restic from GitHub and replacing the current binary with it. It does not rely on any external program (so it'll work everywhere), but still verifies the GPG signature using the embedded GPG public key. By default, the `self-update` command is hidden behind the `selfupdate` built tag, which is only set when restic is built using `build.go`. The reason for this is that downstream distributions will then not include the command by default, so users are encouraged to use the platform-specific distribution mechanism.
550 lines
14 KiB
Go
550 lines
14 KiB
Go
// Copyright 2011 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Package packet implements parsing and serialization of OpenPGP packets, as
|
|
// specified in RFC 4880.
|
|
package packet // import "golang.org/x/crypto/openpgp/packet"
|
|
|
|
import (
|
|
"bufio"
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/des"
|
|
"crypto/rsa"
|
|
"io"
|
|
"math/big"
|
|
|
|
"golang.org/x/crypto/cast5"
|
|
"golang.org/x/crypto/openpgp/errors"
|
|
)
|
|
|
|
// readFull is the same as io.ReadFull except that reading zero bytes returns
|
|
// ErrUnexpectedEOF rather than EOF.
|
|
func readFull(r io.Reader, buf []byte) (n int, err error) {
|
|
n, err = io.ReadFull(r, buf)
|
|
if err == io.EOF {
|
|
err = io.ErrUnexpectedEOF
|
|
}
|
|
return
|
|
}
|
|
|
|
// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
|
|
func readLength(r io.Reader) (length int64, isPartial bool, err error) {
|
|
var buf [4]byte
|
|
_, err = readFull(r, buf[:1])
|
|
if err != nil {
|
|
return
|
|
}
|
|
switch {
|
|
case buf[0] < 192:
|
|
length = int64(buf[0])
|
|
case buf[0] < 224:
|
|
length = int64(buf[0]-192) << 8
|
|
_, err = readFull(r, buf[0:1])
|
|
if err != nil {
|
|
return
|
|
}
|
|
length += int64(buf[0]) + 192
|
|
case buf[0] < 255:
|
|
length = int64(1) << (buf[0] & 0x1f)
|
|
isPartial = true
|
|
default:
|
|
_, err = readFull(r, buf[0:4])
|
|
if err != nil {
|
|
return
|
|
}
|
|
length = int64(buf[0])<<24 |
|
|
int64(buf[1])<<16 |
|
|
int64(buf[2])<<8 |
|
|
int64(buf[3])
|
|
}
|
|
return
|
|
}
|
|
|
|
// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
|
|
// The continuation lengths are parsed and removed from the stream and EOF is
|
|
// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
|
|
type partialLengthReader struct {
|
|
r io.Reader
|
|
remaining int64
|
|
isPartial bool
|
|
}
|
|
|
|
func (r *partialLengthReader) Read(p []byte) (n int, err error) {
|
|
for r.remaining == 0 {
|
|
if !r.isPartial {
|
|
return 0, io.EOF
|
|
}
|
|
r.remaining, r.isPartial, err = readLength(r.r)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
|
|
toRead := int64(len(p))
|
|
if toRead > r.remaining {
|
|
toRead = r.remaining
|
|
}
|
|
|
|
n, err = r.r.Read(p[:int(toRead)])
|
|
r.remaining -= int64(n)
|
|
if n < int(toRead) && err == io.EOF {
|
|
err = io.ErrUnexpectedEOF
|
|
}
|
|
return
|
|
}
|
|
|
|
// partialLengthWriter writes a stream of data using OpenPGP partial lengths.
|
|
// See RFC 4880, section 4.2.2.4.
|
|
type partialLengthWriter struct {
|
|
w io.WriteCloser
|
|
lengthByte [1]byte
|
|
}
|
|
|
|
func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
|
|
for len(p) > 0 {
|
|
for power := uint(14); power < 32; power-- {
|
|
l := 1 << power
|
|
if len(p) >= l {
|
|
w.lengthByte[0] = 224 + uint8(power)
|
|
_, err = w.w.Write(w.lengthByte[:])
|
|
if err != nil {
|
|
return
|
|
}
|
|
var m int
|
|
m, err = w.w.Write(p[:l])
|
|
n += m
|
|
if err != nil {
|
|
return
|
|
}
|
|
p = p[l:]
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (w *partialLengthWriter) Close() error {
|
|
w.lengthByte[0] = 0
|
|
_, err := w.w.Write(w.lengthByte[:])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return w.w.Close()
|
|
}
|
|
|
|
// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
|
|
// underlying Reader returns EOF before the limit has been reached.
|
|
type spanReader struct {
|
|
r io.Reader
|
|
n int64
|
|
}
|
|
|
|
func (l *spanReader) Read(p []byte) (n int, err error) {
|
|
if l.n <= 0 {
|
|
return 0, io.EOF
|
|
}
|
|
if int64(len(p)) > l.n {
|
|
p = p[0:l.n]
|
|
}
|
|
n, err = l.r.Read(p)
|
|
l.n -= int64(n)
|
|
if l.n > 0 && err == io.EOF {
|
|
err = io.ErrUnexpectedEOF
|
|
}
|
|
return
|
|
}
|
|
|
|
// readHeader parses a packet header and returns an io.Reader which will return
|
|
// the contents of the packet. See RFC 4880, section 4.2.
|
|
func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) {
|
|
var buf [4]byte
|
|
_, err = io.ReadFull(r, buf[:1])
|
|
if err != nil {
|
|
return
|
|
}
|
|
if buf[0]&0x80 == 0 {
|
|
err = errors.StructuralError("tag byte does not have MSB set")
|
|
return
|
|
}
|
|
if buf[0]&0x40 == 0 {
|
|
// Old format packet
|
|
tag = packetType((buf[0] & 0x3f) >> 2)
|
|
lengthType := buf[0] & 3
|
|
if lengthType == 3 {
|
|
length = -1
|
|
contents = r
|
|
return
|
|
}
|
|
lengthBytes := 1 << lengthType
|
|
_, err = readFull(r, buf[0:lengthBytes])
|
|
if err != nil {
|
|
return
|
|
}
|
|
for i := 0; i < lengthBytes; i++ {
|
|
length <<= 8
|
|
length |= int64(buf[i])
|
|
}
|
|
contents = &spanReader{r, length}
|
|
return
|
|
}
|
|
|
|
// New format packet
|
|
tag = packetType(buf[0] & 0x3f)
|
|
length, isPartial, err := readLength(r)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if isPartial {
|
|
contents = &partialLengthReader{
|
|
remaining: length,
|
|
isPartial: true,
|
|
r: r,
|
|
}
|
|
length = -1
|
|
} else {
|
|
contents = &spanReader{r, length}
|
|
}
|
|
return
|
|
}
|
|
|
|
// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
|
|
// 4.2.
|
|
func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
|
|
var buf [6]byte
|
|
var n int
|
|
|
|
buf[0] = 0x80 | 0x40 | byte(ptype)
|
|
if length < 192 {
|
|
buf[1] = byte(length)
|
|
n = 2
|
|
} else if length < 8384 {
|
|
length -= 192
|
|
buf[1] = 192 + byte(length>>8)
|
|
buf[2] = byte(length)
|
|
n = 3
|
|
} else {
|
|
buf[1] = 255
|
|
buf[2] = byte(length >> 24)
|
|
buf[3] = byte(length >> 16)
|
|
buf[4] = byte(length >> 8)
|
|
buf[5] = byte(length)
|
|
n = 6
|
|
}
|
|
|
|
_, err = w.Write(buf[:n])
|
|
return
|
|
}
|
|
|
|
// serializeStreamHeader writes an OpenPGP packet header to w where the
|
|
// length of the packet is unknown. It returns a io.WriteCloser which can be
|
|
// used to write the contents of the packet. See RFC 4880, section 4.2.
|
|
func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) {
|
|
var buf [1]byte
|
|
buf[0] = 0x80 | 0x40 | byte(ptype)
|
|
_, err = w.Write(buf[:])
|
|
if err != nil {
|
|
return
|
|
}
|
|
out = &partialLengthWriter{w: w}
|
|
return
|
|
}
|
|
|
|
// Packet represents an OpenPGP packet. Users are expected to try casting
|
|
// instances of this interface to specific packet types.
|
|
type Packet interface {
|
|
parse(io.Reader) error
|
|
}
|
|
|
|
// consumeAll reads from the given Reader until error, returning the number of
|
|
// bytes read.
|
|
func consumeAll(r io.Reader) (n int64, err error) {
|
|
var m int
|
|
var buf [1024]byte
|
|
|
|
for {
|
|
m, err = r.Read(buf[:])
|
|
n += int64(m)
|
|
if err == io.EOF {
|
|
err = nil
|
|
return
|
|
}
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// packetType represents the numeric ids of the different OpenPGP packet types. See
|
|
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
|
|
type packetType uint8
|
|
|
|
const (
|
|
packetTypeEncryptedKey packetType = 1
|
|
packetTypeSignature packetType = 2
|
|
packetTypeSymmetricKeyEncrypted packetType = 3
|
|
packetTypeOnePassSignature packetType = 4
|
|
packetTypePrivateKey packetType = 5
|
|
packetTypePublicKey packetType = 6
|
|
packetTypePrivateSubkey packetType = 7
|
|
packetTypeCompressed packetType = 8
|
|
packetTypeSymmetricallyEncrypted packetType = 9
|
|
packetTypeLiteralData packetType = 11
|
|
packetTypeUserId packetType = 13
|
|
packetTypePublicSubkey packetType = 14
|
|
packetTypeUserAttribute packetType = 17
|
|
packetTypeSymmetricallyEncryptedMDC packetType = 18
|
|
)
|
|
|
|
// peekVersion detects the version of a public key packet about to
|
|
// be read. A bufio.Reader at the original position of the io.Reader
|
|
// is returned.
|
|
func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) {
|
|
bufr = bufio.NewReader(r)
|
|
var verBuf []byte
|
|
if verBuf, err = bufr.Peek(1); err != nil {
|
|
return
|
|
}
|
|
ver = verBuf[0]
|
|
return
|
|
}
|
|
|
|
// Read reads a single OpenPGP packet from the given io.Reader. If there is an
|
|
// error parsing a packet, the whole packet is consumed from the input.
|
|
func Read(r io.Reader) (p Packet, err error) {
|
|
tag, _, contents, err := readHeader(r)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
switch tag {
|
|
case packetTypeEncryptedKey:
|
|
p = new(EncryptedKey)
|
|
case packetTypeSignature:
|
|
var version byte
|
|
// Detect signature version
|
|
if contents, version, err = peekVersion(contents); err != nil {
|
|
return
|
|
}
|
|
if version < 4 {
|
|
p = new(SignatureV3)
|
|
} else {
|
|
p = new(Signature)
|
|
}
|
|
case packetTypeSymmetricKeyEncrypted:
|
|
p = new(SymmetricKeyEncrypted)
|
|
case packetTypeOnePassSignature:
|
|
p = new(OnePassSignature)
|
|
case packetTypePrivateKey, packetTypePrivateSubkey:
|
|
pk := new(PrivateKey)
|
|
if tag == packetTypePrivateSubkey {
|
|
pk.IsSubkey = true
|
|
}
|
|
p = pk
|
|
case packetTypePublicKey, packetTypePublicSubkey:
|
|
var version byte
|
|
if contents, version, err = peekVersion(contents); err != nil {
|
|
return
|
|
}
|
|
isSubkey := tag == packetTypePublicSubkey
|
|
if version < 4 {
|
|
p = &PublicKeyV3{IsSubkey: isSubkey}
|
|
} else {
|
|
p = &PublicKey{IsSubkey: isSubkey}
|
|
}
|
|
case packetTypeCompressed:
|
|
p = new(Compressed)
|
|
case packetTypeSymmetricallyEncrypted:
|
|
p = new(SymmetricallyEncrypted)
|
|
case packetTypeLiteralData:
|
|
p = new(LiteralData)
|
|
case packetTypeUserId:
|
|
p = new(UserId)
|
|
case packetTypeUserAttribute:
|
|
p = new(UserAttribute)
|
|
case packetTypeSymmetricallyEncryptedMDC:
|
|
se := new(SymmetricallyEncrypted)
|
|
se.MDC = true
|
|
p = se
|
|
default:
|
|
err = errors.UnknownPacketTypeError(tag)
|
|
}
|
|
if p != nil {
|
|
err = p.parse(contents)
|
|
}
|
|
if err != nil {
|
|
consumeAll(contents)
|
|
}
|
|
return
|
|
}
|
|
|
|
// SignatureType represents the different semantic meanings of an OpenPGP
|
|
// signature. See RFC 4880, section 5.2.1.
|
|
type SignatureType uint8
|
|
|
|
const (
|
|
SigTypeBinary SignatureType = 0
|
|
SigTypeText = 1
|
|
SigTypeGenericCert = 0x10
|
|
SigTypePersonaCert = 0x11
|
|
SigTypeCasualCert = 0x12
|
|
SigTypePositiveCert = 0x13
|
|
SigTypeSubkeyBinding = 0x18
|
|
SigTypePrimaryKeyBinding = 0x19
|
|
SigTypeDirectSignature = 0x1F
|
|
SigTypeKeyRevocation = 0x20
|
|
SigTypeSubkeyRevocation = 0x28
|
|
)
|
|
|
|
// PublicKeyAlgorithm represents the different public key system specified for
|
|
// OpenPGP. See
|
|
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
|
|
type PublicKeyAlgorithm uint8
|
|
|
|
const (
|
|
PubKeyAlgoRSA PublicKeyAlgorithm = 1
|
|
PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
|
|
PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3
|
|
PubKeyAlgoElGamal PublicKeyAlgorithm = 16
|
|
PubKeyAlgoDSA PublicKeyAlgorithm = 17
|
|
// RFC 6637, Section 5.
|
|
PubKeyAlgoECDH PublicKeyAlgorithm = 18
|
|
PubKeyAlgoECDSA PublicKeyAlgorithm = 19
|
|
)
|
|
|
|
// CanEncrypt returns true if it's possible to encrypt a message to a public
|
|
// key of the given type.
|
|
func (pka PublicKeyAlgorithm) CanEncrypt() bool {
|
|
switch pka {
|
|
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// CanSign returns true if it's possible for a public key of the given type to
|
|
// sign a message.
|
|
func (pka PublicKeyAlgorithm) CanSign() bool {
|
|
switch pka {
|
|
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// CipherFunction represents the different block ciphers specified for OpenPGP. See
|
|
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
|
|
type CipherFunction uint8
|
|
|
|
const (
|
|
Cipher3DES CipherFunction = 2
|
|
CipherCAST5 CipherFunction = 3
|
|
CipherAES128 CipherFunction = 7
|
|
CipherAES192 CipherFunction = 8
|
|
CipherAES256 CipherFunction = 9
|
|
)
|
|
|
|
// KeySize returns the key size, in bytes, of cipher.
|
|
func (cipher CipherFunction) KeySize() int {
|
|
switch cipher {
|
|
case Cipher3DES:
|
|
return 24
|
|
case CipherCAST5:
|
|
return cast5.KeySize
|
|
case CipherAES128:
|
|
return 16
|
|
case CipherAES192:
|
|
return 24
|
|
case CipherAES256:
|
|
return 32
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// blockSize returns the block size, in bytes, of cipher.
|
|
func (cipher CipherFunction) blockSize() int {
|
|
switch cipher {
|
|
case Cipher3DES:
|
|
return des.BlockSize
|
|
case CipherCAST5:
|
|
return 8
|
|
case CipherAES128, CipherAES192, CipherAES256:
|
|
return 16
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// new returns a fresh instance of the given cipher.
|
|
func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
|
|
switch cipher {
|
|
case Cipher3DES:
|
|
block, _ = des.NewTripleDESCipher(key)
|
|
case CipherCAST5:
|
|
block, _ = cast5.NewCipher(key)
|
|
case CipherAES128, CipherAES192, CipherAES256:
|
|
block, _ = aes.NewCipher(key)
|
|
}
|
|
return
|
|
}
|
|
|
|
// readMPI reads a big integer from r. The bit length returned is the bit
|
|
// length that was specified in r. This is preserved so that the integer can be
|
|
// reserialized exactly.
|
|
func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
|
|
var buf [2]byte
|
|
_, err = readFull(r, buf[0:])
|
|
if err != nil {
|
|
return
|
|
}
|
|
bitLength = uint16(buf[0])<<8 | uint16(buf[1])
|
|
numBytes := (int(bitLength) + 7) / 8
|
|
mpi = make([]byte, numBytes)
|
|
_, err = readFull(r, mpi)
|
|
// According to RFC 4880 3.2. we should check that the MPI has no leading
|
|
// zeroes (at least when not an encrypted MPI?), but this implementation
|
|
// does generate leading zeroes, so we keep accepting them.
|
|
return
|
|
}
|
|
|
|
// writeMPI serializes a big integer to w.
|
|
func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
|
|
// Note that we can produce leading zeroes, in violation of RFC 4880 3.2.
|
|
// Implementations seem to be tolerant of them, and stripping them would
|
|
// make it complex to guarantee matching re-serialization.
|
|
_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
|
|
if err == nil {
|
|
_, err = w.Write(mpiBytes)
|
|
}
|
|
return
|
|
}
|
|
|
|
// writeBig serializes a *big.Int to w.
|
|
func writeBig(w io.Writer, i *big.Int) error {
|
|
return writeMPI(w, uint16(i.BitLen()), i.Bytes())
|
|
}
|
|
|
|
// padToKeySize left-pads a MPI with zeroes to match the length of the
|
|
// specified RSA public.
|
|
func padToKeySize(pub *rsa.PublicKey, b []byte) []byte {
|
|
k := (pub.N.BitLen() + 7) / 8
|
|
if len(b) >= k {
|
|
return b
|
|
}
|
|
bb := make([]byte, k)
|
|
copy(bb[len(bb)-len(b):], b)
|
|
return bb
|
|
}
|
|
|
|
// CompressionAlgo Represents the different compression algorithms
|
|
// supported by OpenPGP (except for BZIP2, which is not currently
|
|
// supported). See Section 9.3 of RFC 4880.
|
|
type CompressionAlgo uint8
|
|
|
|
const (
|
|
CompressionNone CompressionAlgo = 0
|
|
CompressionZIP CompressionAlgo = 1
|
|
CompressionZLIB CompressionAlgo = 2
|
|
)
|