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 }
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 }
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 }
// 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 }
// 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") }
// 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 }
// 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 }
// 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 }