Пример #1
0
func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
	var subKey Subkey
	subKey.PublicKey = pub
	subKey.PrivateKey = priv
	for {
		p, err := packets.Next()
		if err == io.EOF {
			return io.ErrUnexpectedEOF
		}
		if err != nil {
			return errors.StructuralError("subkey signature invalid: " + err.Error())
		}
		sig, ok := p.(*packet.Signature)
		if !ok {
			return errors.StructuralError(fmt.Sprintf("subkey packet not followed by signature (got %T)", p))
		}
		if st := sig.SigType; st != packet.SigTypeSubkeyBinding && st != packet.SigTypeSubkeyRevocation {

			// Note(maxtaco):
			// We used to error out here, but instead, let's fast-forward past
			// packets that are in the wrong place (like misplaced 0x13 signatures)
			// until we get to one that works.  For a test case,
			// see TestWithBadSubkeySignaturePackets.
			continue
		}
		subKey.Sig = sig
		err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
		if err != nil {
			return errors.StructuralError("subkey signature invalid: " + err.Error())
		}
		break
	}
	e.Subkeys = append(e.Subkeys, subKey)
	return nil
}
Пример #2
0
func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
	var subKey Subkey
	subKey.PublicKey = pub
	subKey.PrivateKey = priv
	p, err := packets.Next()
	if err == io.EOF {
		return io.ErrUnexpectedEOF
	}
	if err != nil {
		return errors.StructuralError("subkey signature invalid: " + err.Error())
	}
	var ok bool
	subKey.Sig, ok = p.(*packet.Signature)
	if !ok {
		return errors.StructuralError("subkey packet not followed by signature")
	}
	if subKey.Sig.SigType != packet.SigTypeSubkeyBinding && subKey.Sig.SigType != packet.SigTypeSubkeyRevocation {
		return errors.StructuralError("subkey signature with wrong type")
	}
	err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
	if err != nil {
		return errors.StructuralError("subkey signature invalid: " + err.Error())
	}
	e.Subkeys = append(e.Subkeys, subKey)
	return nil
}
Пример #3
0
func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
	var subKey Subkey
	subKey.PublicKey = pub
	subKey.PrivateKey = priv
	var lastErr error
	for {
		p, err := packets.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return errors.StructuralError("subkey signature invalid: " + err.Error())
		}
		sig, ok := p.(*packet.Signature)
		if !ok {
			// Hit a non-signature packet, so assume we're up to the next key
			packets.Unread(p)
			break
		}
		if st := sig.SigType; st != packet.SigTypeSubkeyBinding && st != packet.SigTypeSubkeyRevocation {

			// Note(maxtaco):
			// We used to error out here, but instead, let's fast-forward past
			// packets that are in the wrong place (like misplaced 0x13 signatures)
			// until we get to one that works.  For a test case,
			// see TestWithBadSubkeySignaturePackets.

			continue
		}
		err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig)
		if err != nil {
			// Non valid signature, so again, no need to abandon all hope, just continue;
			// make a note of the error we hit.
			lastErr = errors.StructuralError("subkey signature invalid: " + err.Error())
			continue
		}
		switch sig.SigType {
		case packet.SigTypeSubkeyBinding:
			// First writer wins
			if subKey.Sig == nil {
				subKey.Sig = sig
			}
		case packet.SigTypeSubkeyRevocation:
			// First writer wins
			if subKey.Revocation == nil {
				subKey.Revocation = sig
			}
		}
	}
	if subKey.Sig != nil {
		e.Subkeys = append(e.Subkeys, subKey)
	} else {
		if lastErr == nil {
			lastErr = errors.StructuralError("Subkey wasn't signed; expected a 'binding' signature")
		}
		e.BadSubkeys = append(e.BadSubkeys, BadSubkey{Subkey: subKey, Err: lastErr})
	}
	return nil
}
Пример #4
0
// readSignedMessage reads a possibly signed message if mdin is non-zero then
// that structure is updated and returned. Otherwise a fresh MessageDetails is
// used.
func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) {
	if mdin == nil {
		mdin = new(MessageDetails)
	}
	md = mdin

	var p packet.Packet
	var h hash.Hash
	var wrappedHash hash.Hash
FindLiteralData:
	for {
		p, err = packets.Next()
		if err != nil {
			return nil, err
		}
		switch p := p.(type) {
		case *packet.Compressed:
			if err := packets.Push(p.Body); err != nil {
				return nil, err
			}
		case *packet.OnePassSignature:
			if !p.IsLast {
				return nil, errors.UnsupportedError("nested signatures")
			}

			h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
			if err != nil {
				md = nil
				return
			}

			md.IsSigned = true
			md.SignedByKeyId = p.KeyId
			keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
			if len(keys) > 0 {
				md.SignedBy = &keys[0]
			}
		case *packet.LiteralData:
			md.LiteralData = p
			break FindLiteralData
		}
	}

	if md.SignedBy != nil {
		md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
	} else if md.decrypted != nil {
		md.UnverifiedBody = checkReader{md}
	} else {
		md.UnverifiedBody = md.LiteralData.Body
	}

	return md, nil
}
Пример #5
0
// readToNextPublicKey reads packets until the start of the entity and leaves
// the first packet of the new entity in the Reader.
func readToNextPublicKey(packets *packet.Reader) (err error) {
	var p packet.Packet
	for {
		p, err = packets.Next()
		if err == io.EOF {
			return
		} else if err != nil {
			if _, ok := err.(errors.UnsupportedError); ok {
				err = nil
				continue
			}
			return
		}

		if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
			packets.Unread(p)
			return
		}
	}

	panic("unreachable")
}
Пример #6
0
// ReadEntity reads an entity (public key, identities, subkeys etc) from the
// given Reader.
func ReadEntity(packets *packet.Reader) (*Entity, error) {
	e := new(Entity)
	e.Identities = make(map[string]*Identity)

	p, err := packets.Next()
	if err != nil {
		return nil, err
	}

	var ok bool
	if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
		if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
			packets.Unread(p)
			return nil, errors.StructuralError("first packet was not a public/private key")
		} else {
			e.PrimaryKey = &e.PrivateKey.PublicKey
		}
	}

	if !e.PrimaryKey.PubKeyAlgo.CanSign() {
		return nil, errors.StructuralError("primary key cannot be used for signatures")
	}

	var current *Identity
	var revocations []*packet.Signature
EachPacket:
	for {
		p, err := packets.Next()
		if err == io.EOF {
			break
		} else if err != nil {
			return nil, err
		}
		switch pkt := p.(type) {
		case *packet.UserId:
			current = new(Identity)
			current.Name = pkt.Id
			current.UserId = pkt
			e.Identities[pkt.Id] = current

			for {
				p, err = packets.Next()
				if err == io.EOF {
					return nil, io.ErrUnexpectedEOF
				} else if err != nil {
					return nil, err
				}

				sig, ok := p.(*packet.Signature)
				if !ok {
					return nil, errors.StructuralError("user ID packet not followed by self-signature")
				}

				if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
					if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
						return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error())
					}
					current.SelfSignature = sig
					break
				}
				current.Signatures = append(current.Signatures, sig)
			}
		case *packet.Signature:
			if pkt.SigType == packet.SigTypeKeyRevocation {
				revocations = append(revocations, pkt)
			} else if pkt.SigType == packet.SigTypeDirectSignature {
				// TODO: RFC4880 5.2.1 permits signatures
				// directly on keys (eg. to bind additional
				// revocation keys).
			} else if current == nil {
				return nil, errors.StructuralError("signature packet found before user id packet")
			} else {
				current.Signatures = append(current.Signatures, pkt)
			}
		case *packet.PrivateKey:
			if pkt.IsSubkey == false {
				packets.Unread(p)
				break EachPacket
			}
			err = addSubkey(e, packets, &pkt.PublicKey, pkt)
			if err != nil {
				return nil, err
			}
		case *packet.PublicKey:
			if pkt.IsSubkey == false {
				packets.Unread(p)
				break EachPacket
			}
			err = addSubkey(e, packets, pkt, nil)
			if err != nil {
				return nil, err
			}
		default:
			// we ignore unknown packets
		}
	}

	if len(e.Identities) == 0 {
		return nil, errors.StructuralError("entity without any identities")
	}

	for _, revocation := range revocations {
		err = e.PrimaryKey.VerifyRevocationSignature(revocation)
		if err == nil {
			e.Revocations = append(e.Revocations, revocation)
		} else {
			// TODO: RFC 4880 5.2.3.15 defines revocation keys.
			return nil, errors.StructuralError("revocation signature signed by alternate key")
		}
	}

	return e, nil
}
Пример #7
0
// ReadEntity reads an entity (public key, identities, subkeys etc) from the
// given Reader.
func ReadEntity(packets *packet.Reader) (*Entity, error) {
	e := new(Entity)
	e.Identities = make(map[string]*Identity)

	p, err := packets.Next()
	if err != nil {
		return nil, err
	}

	var ok bool
	if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
		if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
			packets.Unread(p)
			return nil, errors.StructuralError("first packet was not a public/private key")
		} else {
			e.PrimaryKey = &e.PrivateKey.PublicKey
		}
	}

	if !e.PrimaryKey.PubKeyAlgo.CanSign() {
		return nil, errors.StructuralError("primary key cannot be used for signatures")
	}

	var current *Identity
	var revocations []*packet.Signature
EachPacket:
	for {
		p, err := packets.Next()
		if err == io.EOF {
			break
		} else if err != nil {
			return nil, err
		}
		switch pkt := p.(type) {
		case *packet.UserId:

			// Make a new Identity object, that we might wind up throwing away.
			// We'll only add it if we get a valid self-signature over this
			// userID.
			current = new(Identity)
			current.Name = pkt.Id
			current.UserId = pkt
		case *packet.Signature:

			// First handle the case of a self-signature. According to RFC8440,
			// Section 5.2.3.3, if there are several self-signatures,
			// we should take the newer one.
			if current != nil &&
				(current.SelfSignature == nil || pkt.CreationTime.After(current.SelfSignature.CreationTime)) &&
				(pkt.SigType == packet.SigTypePositiveCert || pkt.SigType == packet.SigTypeGenericCert) &&
				pkt.IssuerKeyId != nil &&
				*pkt.IssuerKeyId == e.PrimaryKey.KeyId {

				if err = e.PrimaryKey.VerifyUserIdSignature(current.Name, e.PrimaryKey, pkt); err == nil {

					current.SelfSignature = pkt

					// NOTE(maxtaco) 2016.01.11
					// Only register an identity once we've gotten a valid self-signature.
					// It's possible therefore for us to throw away `current` in the case
					// no valid self-signatures were found. That's OK as long as there are
					// other identies that make sense.
					//
					// NOTE! We might later see a revocation for this very same UID, and it
					// won't be undone. We've preserved this feature from the original
					// Google OpenPGP we forked from.
					e.Identities[current.Name] = current
				} else {
					// We really should warn that there was a failure here. Not raise an error
					// since this really shouldn't be a fail-stop error.
				}
			} else if pkt.SigType == packet.SigTypeKeyRevocation {
				// These revocations won't revoke UIDs as handled above, so lookout!
				revocations = append(revocations, pkt)
			} else if pkt.SigType == packet.SigTypeDirectSignature {
				// TODO: RFC4880 5.2.1 permits signatures
				// directly on keys (eg. to bind additional
				// revocation keys).
			} else if current == nil {
				return nil, errors.StructuralError("signature packet found before user id packet")
			} else {
				current.Signatures = append(current.Signatures, pkt)
			}
		case *packet.PrivateKey:
			if pkt.IsSubkey == false {
				packets.Unread(p)
				break EachPacket
			}
			err = addSubkey(e, packets, &pkt.PublicKey, pkt)
			if err != nil {
				return nil, err
			}
		case *packet.PublicKey:
			if pkt.IsSubkey == false {
				packets.Unread(p)
				break EachPacket
			}
			err = addSubkey(e, packets, pkt, nil)
			if err != nil {
				return nil, err
			}
		default:
			// we ignore unknown packets
		}
	}

	if len(e.Identities) == 0 {
		return nil, errors.StructuralError("entity without any identities")
	}

	for _, revocation := range revocations {
		err = e.PrimaryKey.VerifyRevocationSignature(revocation)
		if err == nil {
			e.Revocations = append(e.Revocations, revocation)
		} else {
			// TODO: RFC 4880 5.2.3.15 defines revocation keys.
			return nil, errors.StructuralError("revocation signature signed by alternate key")
		}
	}

	return e, nil
}
Пример #8
0
// ReadEntity reads an entity (public key, identities, subkeys etc) from the
// given Reader.
func ReadEntity(packets *packet.Reader) (*Entity, error) {
	e := new(Entity)
	e.Identities = make(map[string]*Identity)

	p, err := packets.Next()
	if err != nil {
		return nil, err
	}

	var ok bool
	if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
		if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
			packets.Unread(p)
			return nil, errors.StructuralError("first packet was not a public/private key")
		} else {
			e.PrimaryKey = &e.PrivateKey.PublicKey
		}
	}

	if !e.PrimaryKey.PubKeyAlgo.CanSign() {
		return nil, errors.StructuralError("primary key cannot be used for signatures")
	}

	var current *Identity
	var revocations []*packet.Signature
EachPacket:
	for {
		p, err := packets.Next()
		if err == io.EOF {
			break
		} else if err != nil {
			return nil, err
		}
		switch pkt := p.(type) {
		case *packet.UserId:

			// Make a new Identity object, that we might wind up throwing away.
			// We'll only add it if we get a valid self-signature over this
			// userID.
			current = new(Identity)
			current.Name = pkt.Id
			current.UserId = pkt
		case *packet.Signature:

			// These are signatures by other people on this key. Let's just ignore them
			// from the beginning, since they shouldn't affect our key decoding one way
			// or the other.
			if pkt.IssuerKeyId != nil && *pkt.IssuerKeyId != e.PrimaryKey.KeyId {
				continue
			}

			// If this is a signature made by the keyholder, and the signature has stubbed out
			// critical packets, then *now* we need to bail out.
			if e := pkt.StubbedOutCriticalError; e != nil {
				return nil, e
			}

			// Next handle the case of a self-signature. According to RFC8440,
			// Section 5.2.3.3, if there are several self-signatures,
			// we should take the newer one.  If they were both created
			// at the same time, but one of them has keyflags specified and the
			// other doesn't, keep the one with the keyflags. We have actually
			// seen this in the wild (see the 'Yield' test in read_test.go).
			// If there is a tie, and both have the same value for FlagsValid,
			// then "last writer wins."
			//
			// HOWEVER! We have seen yet more keys in the wild (see the 'Spiros'
			// test in read_test.go), in which the later self-signature is a bunch
			// of junk, and doesn't even specify key flags. Does it really make
			// sense to overwrite reasonable key flags with the empty set? I'm not
			// sure what that would be trying to achieve, and plus GPG seems to be
			// ok with this situation, and ignores the later (empty) keyflag set.
			// So further tighten our overwrite rules, and only allow the later
			// signature to overwrite the earlier signature if so doing won't
			// trash the key flags.
			if current != nil &&
				(current.SelfSignature == nil ||
					(!pkt.CreationTime.Before(current.SelfSignature.CreationTime) &&
						(pkt.FlagsValid || !current.SelfSignature.FlagsValid))) &&
				(pkt.SigType == packet.SigTypePositiveCert || pkt.SigType == packet.SigTypeGenericCert) &&
				pkt.IssuerKeyId != nil &&
				*pkt.IssuerKeyId == e.PrimaryKey.KeyId {

				if err = e.PrimaryKey.VerifyUserIdSignature(current.Name, e.PrimaryKey, pkt); err == nil {

					current.SelfSignature = pkt

					// NOTE(maxtaco) 2016.01.11
					// Only register an identity once we've gotten a valid self-signature.
					// It's possible therefore for us to throw away `current` in the case
					// no valid self-signatures were found. That's OK as long as there are
					// other identies that make sense.
					//
					// NOTE! We might later see a revocation for this very same UID, and it
					// won't be undone. We've preserved this feature from the original
					// Google OpenPGP we forked from.
					e.Identities[current.Name] = current
				} else {
					// We really should warn that there was a failure here. Not raise an error
					// since this really shouldn't be a fail-stop error.
				}
			} else if pkt.SigType == packet.SigTypeKeyRevocation {
				// These revocations won't revoke UIDs as handled above, so lookout!
				revocations = append(revocations, pkt)
			} else if pkt.SigType == packet.SigTypeDirectSignature {
				// TODO: RFC4880 5.2.1 permits signatures
				// directly on keys (eg. to bind additional
				// revocation keys).
			} else if current == nil {
				// NOTE(maxtaco)
				//
				// See https://github.com/keybase/client/issues/2666
				//
				// There might have been a user attribute picture before this signature,
				// in which case this is still a valid PGP key. In the future we might
				// not ignore user attributes (like picture). But either way, it doesn't
				// make sense to bail out here. Keep looking for other valid signatures.
				//
				// Used to be:
				//    return nil, errors.StructuralError("signature packet found before user id packet")
			} else {
				current.Signatures = append(current.Signatures, pkt)
			}
		case *packet.PrivateKey:
			if pkt.IsSubkey == false {
				packets.Unread(p)
				break EachPacket
			}
			err = addSubkey(e, packets, &pkt.PublicKey, pkt)
			if err != nil {
				return nil, err
			}
		case *packet.PublicKey:
			if pkt.IsSubkey == false {
				packets.Unread(p)
				break EachPacket
			}
			err = addSubkey(e, packets, pkt, nil)
			if err != nil {
				return nil, err
			}
		default:
			// we ignore unknown packets
		}
	}

	if len(e.Identities) == 0 {
		return nil, errors.StructuralError("entity without any identities")
	}

	for _, revocation := range revocations {
		err = e.PrimaryKey.VerifyRevocationSignature(revocation)
		if err == nil {
			e.Revocations = append(e.Revocations, revocation)
		} else {
			// TODO: RFC 4880 5.2.3.15 defines revocation keys.
			return nil, errors.StructuralError("revocation signature signed by alternate key")
		}
	}

	return e, nil
}