Skip to content

Commit cfbd6f6

Browse files
authored
Merge pull request #272 from davrux/main
Allows Key Flags override, fixes #205
2 parents ef10ec5 + 68c5c41 commit cfbd6f6

File tree

3 files changed

+105
-22
lines changed

3 files changed

+105
-22
lines changed

openpgp/packet/config.go

+12
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ type Config struct {
173173
// weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks.
174174
// The default behavior, when the config or flag is nil, is to enable the feature.
175175
NonDeterministicSignaturesViaNotation *bool
176+
177+
// InsecureAllowAllKeyFlagsWhenMissing determines how a key without valid key flags is handled.
178+
// When set to true, a key without flags is treated as if all flags are enabled.
179+
// This behavior is consistent with GPG.
180+
InsecureAllowAllKeyFlagsWhenMissing bool
176181
}
177182

178183
func (c *Config) Random() io.Reader {
@@ -403,6 +408,13 @@ func (c *Config) RandomizeSignaturesViaNotation() bool {
403408
return *c.NonDeterministicSignaturesViaNotation
404409
}
405410

411+
func (c *Config) AllowAllKeyFlagsWhenMissing() bool {
412+
if c == nil {
413+
return false
414+
}
415+
return c.InsecureAllowAllKeyFlagsWhenMissing
416+
}
417+
406418
// BoolPointer is a helper function to set a boolean pointer in the Config.
407419
// e.g., config.CheckPacketSequence = BoolPointer(true)
408420
func BoolPointer(value bool) *bool {

openpgp/v2/keys.go

+38-20
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func (e *Entity) EncryptionKey(now time.Time, config *packet.Config) (Key, bool)
116116
for i, subkey := range e.Subkeys {
117117
subkeySelfSig, err := subkey.Verify(now, config) // subkey has to be valid at time now
118118
if err == nil &&
119-
isValidEncryptionKey(subkeySelfSig, subkey.PublicKey.PubKeyAlgo) &&
119+
isValidEncryptionKey(subkeySelfSig, subkey.PublicKey.PubKeyAlgo, config) &&
120120
checkKeyRequirements(subkey.PublicKey, config) == nil &&
121121
(maxTime.IsZero() || subkeySelfSig.CreationTime.Unix() >= maxTime.Unix()) {
122122
candidateSubkey = i
@@ -138,7 +138,7 @@ func (e *Entity) EncryptionKey(now time.Time, config *packet.Config) (Key, bool)
138138

139139
// If we don't have any subkeys for encryption and the primary key
140140
// is marked as OK to encrypt with, then we can use it.
141-
if isValidEncryptionKey(primarySelfSignature, e.PrimaryKey.PubKeyAlgo) {
141+
if isValidEncryptionKey(primarySelfSignature, e.PrimaryKey.PubKeyAlgo, config) {
142142
return Key{
143143
Entity: e,
144144
PrimarySelfSignature: primarySelfSignature,
@@ -164,12 +164,12 @@ func (e *Entity) DecryptionKeys(id uint64, date time.Time, config *packet.Config
164164
for _, subkey := range e.Subkeys {
165165
subkeySelfSig, err := subkey.LatestValidBindingSignature(date, config)
166166
if err == nil &&
167-
(config.AllowDecryptionWithSigningKeys() || isValidEncryptionKey(subkeySelfSig, subkey.PublicKey.PubKeyAlgo)) &&
167+
(config.AllowDecryptionWithSigningKeys() || isValidEncryptionKey(subkeySelfSig, subkey.PublicKey.PubKeyAlgo, config)) &&
168168
(id == 0 || subkey.PublicKey.KeyId == id) {
169169
keys = append(keys, Key{subkey.Primary, primarySelfSignature, subkey.PublicKey, subkey.PrivateKey, subkeySelfSig})
170170
}
171171
}
172-
if config.AllowDecryptionWithSigningKeys() || isValidEncryptionKey(primarySelfSignature, e.PrimaryKey.PubKeyAlgo) {
172+
if config.AllowDecryptionWithSigningKeys() || isValidEncryptionKey(primarySelfSignature, e.PrimaryKey.PubKeyAlgo, config) {
173173
keys = append(keys, Key{e, primarySelfSignature, e.PrimaryKey, e.PrivateKey, primarySelfSignature})
174174
}
175175
return
@@ -219,8 +219,8 @@ func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int, config
219219
for idx, subkey := range e.Subkeys {
220220
subkeySelfSig, err := subkey.Verify(now, config)
221221
if err == nil &&
222-
(flags&packet.KeyFlagCertify == 0 || isValidCertificationKey(subkeySelfSig, subkey.PublicKey.PubKeyAlgo)) &&
223-
(flags&packet.KeyFlagSign == 0 || isValidSigningKey(subkeySelfSig, subkey.PublicKey.PubKeyAlgo)) &&
222+
(flags&packet.KeyFlagCertify == 0 || isValidCertificationKey(subkeySelfSig, subkey.PublicKey.PubKeyAlgo, config)) &&
223+
(flags&packet.KeyFlagSign == 0 || isValidSigningKey(subkeySelfSig, subkey.PublicKey.PubKeyAlgo, config)) &&
224224
checkKeyRequirements(subkey.PublicKey, config) == nil &&
225225
(maxTime.IsZero() || subkeySelfSig.CreationTime.Unix() >= maxTime.Unix()) &&
226226
(id == 0 || subkey.PublicKey.KeyId == id) {
@@ -243,8 +243,8 @@ func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int, config
243243

244244
// If we don't have any subkeys for signing and the primary key
245245
// is marked as OK to sign with, then we can use it.
246-
if (flags&packet.KeyFlagCertify == 0 || isValidCertificationKey(primarySelfSignature, e.PrimaryKey.PubKeyAlgo)) &&
247-
(flags&packet.KeyFlagSign == 0 || isValidSigningKey(primarySelfSignature, e.PrimaryKey.PubKeyAlgo)) &&
246+
if (flags&packet.KeyFlagCertify == 0 || isValidCertificationKey(primarySelfSignature, e.PrimaryKey.PubKeyAlgo, config)) &&
247+
(flags&packet.KeyFlagSign == 0 || isValidSigningKey(primarySelfSignature, e.PrimaryKey.PubKeyAlgo, config)) &&
248248
(id == 0 || e.PrimaryKey.KeyId == id) {
249249
return Key{
250250
Entity: e,
@@ -770,20 +770,38 @@ func checkKeyRequirements(usedKey *packet.PublicKey, config *packet.Config) erro
770770
return nil
771771
}
772772

773-
func isValidSigningKey(signature *packet.Signature, algo packet.PublicKeyAlgorithm) bool {
774-
return algo.CanSign() &&
775-
signature.FlagsValid &&
776-
signature.FlagSign
773+
func isValidSigningKey(signature *packet.Signature, algo packet.PublicKeyAlgorithm, config *packet.Config) bool {
774+
if !algo.CanSign() {
775+
return false
776+
}
777+
778+
if signature.FlagsValid {
779+
return signature.FlagSign
780+
}
781+
782+
return config.AllowAllKeyFlagsWhenMissing()
777783
}
778784

779-
func isValidCertificationKey(signature *packet.Signature, algo packet.PublicKeyAlgorithm) bool {
780-
return algo.CanSign() &&
781-
signature.FlagsValid &&
782-
signature.FlagCertify
785+
func isValidCertificationKey(signature *packet.Signature, algo packet.PublicKeyAlgorithm, config *packet.Config) bool {
786+
if !algo.CanSign() {
787+
return false
788+
}
789+
790+
if signature.FlagsValid {
791+
return signature.FlagCertify
792+
}
793+
794+
return config.AllowAllKeyFlagsWhenMissing()
783795
}
784796

785-
func isValidEncryptionKey(signature *packet.Signature, algo packet.PublicKeyAlgorithm) bool {
786-
return algo.CanEncrypt() &&
787-
signature.FlagsValid &&
788-
(signature.FlagEncryptCommunications || signature.FlagEncryptStorage)
797+
func isValidEncryptionKey(signature *packet.Signature, algo packet.PublicKeyAlgorithm, config *packet.Config) bool {
798+
if !algo.CanEncrypt() {
799+
return false
800+
}
801+
802+
if signature.FlagsValid {
803+
return signature.FlagEncryptCommunications || signature.FlagEncryptStorage
804+
}
805+
806+
return config.AllowAllKeyFlagsWhenMissing()
789807
}

openpgp/v2/keys_test.go

+55-2
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,6 @@ func TestKeyWithRevokedSubKey(t *testing.T) {
585585
if len(subKey.Bindings) == 0 {
586586
t.Fatalf("no binding subkey signature")
587587
}
588-
589588
}
590589

591590
func TestSubkeyRevocation(t *testing.T) {
@@ -683,7 +682,6 @@ func TestKeyWithSubKeyAndBadSelfSigOrder(t *testing.T) {
683682
if lifetime := selfSig.KeyLifetimeSecs; lifetime != nil {
684683
t.Errorf("The signature has a key lifetime (%d), but it should be nil", *lifetime)
685684
}
686-
687685
}
688686

689687
func TestIdVerification(t *testing.T) {
@@ -1063,6 +1061,7 @@ func TestAddUserId(t *testing.T) {
10631061
t.Fatal(err)
10641062
}
10651063
}
1064+
10661065
func TestAddSubkey(t *testing.T) {
10671066
entity, err := NewEntity("Golang Gopher", "Test Key", "[email protected]", nil)
10681067
if err != nil {
@@ -2022,3 +2021,57 @@ NciH07RTRuMS/aRhRg4OB8PQROmTnZ+iZS0=
20222021
t.Fatal(err)
20232022
}
20242023
}
2024+
2025+
func TestAllowAllKeyFlagsWhenMissing(t *testing.T) {
2026+
// Make a master key.
2027+
entity, err := NewEntity("Golang Gopher", "Test Key", "[email protected]", nil)
2028+
if err != nil {
2029+
t.Fatal(err)
2030+
}
2031+
2032+
config := &packet.Config{}
2033+
2034+
primarySelfSignature, err := entity.VerifyPrimaryKey(time.Now(), config)
2035+
if err != nil {
2036+
t.Fatal(err)
2037+
}
2038+
2039+
if !entity.PrimaryKey.PubKeyAlgo.CanEncrypt() ||
2040+
!entity.PrimaryKey.PubKeyAlgo.CanSign() {
2041+
t.Fatal("PubKeyAlgo must be valid for signature and encryption")
2042+
}
2043+
2044+
/// Flags valid, but not set.
2045+
primarySelfSignature.FlagsValid = true
2046+
primarySelfSignature.FlagSign = false
2047+
primarySelfSignature.FlagCertify = false
2048+
primarySelfSignature.FlagEncryptCommunications = false
2049+
2050+
if isValidSigningKey(primarySelfSignature, entity.PrimaryKey.PubKeyAlgo, config) {
2051+
t.Error("isValidSigningKey must be false")
2052+
}
2053+
2054+
if isValidEncryptionKey(primarySelfSignature, entity.PrimaryKey.PubKeyAlgo, config) {
2055+
t.Error("isValidEncryptionKey must be false")
2056+
}
2057+
2058+
if isValidCertificationKey(primarySelfSignature, entity.PrimaryKey.PubKeyAlgo, config) {
2059+
t.Error("isValidCertificationKey must be false")
2060+
}
2061+
2062+
/// Flags not valid, but InsecureAllowAllKeyFlagsWhenMissing set.
2063+
primarySelfSignature.FlagsValid = false
2064+
config = &packet.Config{InsecureAllowAllKeyFlagsWhenMissing: true}
2065+
2066+
if !isValidSigningKey(primarySelfSignature, entity.PrimaryKey.PubKeyAlgo, config) {
2067+
t.Error("isValidSigningKey must be true when InsecureAllowAllKeyFlagsWhenMissing is true")
2068+
}
2069+
2070+
if !isValidEncryptionKey(primarySelfSignature, entity.PrimaryKey.PubKeyAlgo, config) {
2071+
t.Error("isValidEncryptionKey must be true when InsecureAllowAllKeyFlagsWhenMissing is true")
2072+
}
2073+
2074+
if !isValidCertificationKey(primarySelfSignature, entity.PrimaryKey.PubKeyAlgo, config) {
2075+
t.Error("isValidCertificationKey must be true when InsecureAllowAllKeyFlagsWhenMissing is true")
2076+
}
2077+
}

0 commit comments

Comments
 (0)