main
1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "crypto"
9 "crypto/rand"
10 "io"
11 "math/big"
12 "time"
13
14 "github.com/ProtonMail/go-crypto/openpgp/s2k"
15)
16
17var (
18 defaultRejectPublicKeyAlgorithms = map[PublicKeyAlgorithm]bool{
19 PubKeyAlgoElGamal: true,
20 PubKeyAlgoDSA: true,
21 }
22 defaultRejectHashAlgorithms = map[crypto.Hash]bool{
23 crypto.MD5: true,
24 crypto.RIPEMD160: true,
25 }
26 defaultRejectMessageHashAlgorithms = map[crypto.Hash]bool{
27 crypto.SHA1: true,
28 crypto.MD5: true,
29 crypto.RIPEMD160: true,
30 }
31 defaultRejectCurves = map[Curve]bool{
32 CurveSecP256k1: true,
33 }
34)
35
36// A global feature flag to indicate v5 support.
37// Can be set via a build tag, e.g.: `go build -tags v5 ./...`
38// If the build tag is missing config_v5.go will set it to true.
39//
40// Disables parsing of v5 keys and v5 signatures.
41// These are non-standard entities, which in the crypto-refresh have been superseded
42// by v6 keys, v6 signatures and SEIPDv2 encrypted data, respectively.
43var V5Disabled = false
44
45// Config collects a number of parameters along with sensible defaults.
46// A nil *Config is valid and results in all default values.
47type Config struct {
48 // Rand provides the source of entropy.
49 // If nil, the crypto/rand Reader is used.
50 Rand io.Reader
51 // DefaultHash is the default hash function to be used.
52 // If zero, SHA-256 is used.
53 DefaultHash crypto.Hash
54 // DefaultCipher is the cipher to be used.
55 // If zero, AES-128 is used.
56 DefaultCipher CipherFunction
57 // Time returns the current time as the number of seconds since the
58 // epoch. If Time is nil, time.Now is used.
59 Time func() time.Time
60 // DefaultCompressionAlgo is the compression algorithm to be
61 // applied to the plaintext before encryption. If zero, no
62 // compression is done.
63 DefaultCompressionAlgo CompressionAlgo
64 // CompressionConfig configures the compression settings.
65 CompressionConfig *CompressionConfig
66 // S2K (String to Key) config, used for key derivation in the context of secret key encryption
67 // and password-encrypted data.
68 // If nil, the default configuration is used
69 S2KConfig *s2k.Config
70 // Iteration count for Iterated S2K (String to Key).
71 // Only used if sk2.Mode is nil.
72 // This value is duplicated here from s2k.Config for backwards compatibility.
73 // It determines the strength of the passphrase stretching when
74 // the said passphrase is hashed to produce a key. S2KCount
75 // should be between 65536 and 65011712, inclusive. If Config
76 // is nil or S2KCount is 0, the value 16777216 used. Not all
77 // values in the above range can be represented. S2KCount will
78 // be rounded up to the next representable value if it cannot
79 // be encoded exactly. When set, it is strongly encrouraged to
80 // use a value that is at least 65536. See RFC 4880 Section
81 // 3.7.1.3.
82 //
83 // Deprecated: SK2Count should be configured in S2KConfig instead.
84 S2KCount int
85 // RSABits is the number of bits in new RSA keys made with NewEntity.
86 // If zero, then 2048 bit keys are created.
87 RSABits int
88 // The public key algorithm to use - will always create a signing primary
89 // key and encryption subkey.
90 Algorithm PublicKeyAlgorithm
91 // Some known primes that are optionally prepopulated by the caller
92 RSAPrimes []*big.Int
93 // Curve configures the desired packet.Curve if the Algorithm is PubKeyAlgoECDSA,
94 // PubKeyAlgoEdDSA, or PubKeyAlgoECDH. If empty Curve25519 is used.
95 Curve Curve
96 // AEADConfig configures the use of the new AEAD Encrypted Data Packet,
97 // defined in the draft of the next version of the OpenPGP specification.
98 // If a non-nil AEADConfig is passed, usage of this packet is enabled. By
99 // default, it is disabled. See the documentation of AEADConfig for more
100 // configuration options related to AEAD.
101 // **Note: using this option may break compatibility with other OpenPGP
102 // implementations, as well as future versions of this library.**
103 AEADConfig *AEADConfig
104 // V6Keys configures version 6 key generation. If false, this package still
105 // supports version 6 keys, but produces version 4 keys.
106 V6Keys bool
107 // Minimum RSA key size allowed for key generation and message signing, verification and encryption.
108 MinRSABits uint16
109 // Reject insecure algorithms, only works with v2 api
110 RejectPublicKeyAlgorithms map[PublicKeyAlgorithm]bool
111 RejectHashAlgorithms map[crypto.Hash]bool
112 RejectMessageHashAlgorithms map[crypto.Hash]bool
113 RejectCurves map[Curve]bool
114 // "The validity period of the key. This is the number of seconds after
115 // the key creation time that the key expires. If this is not present
116 // or has a value of zero, the key never expires. This is found only on
117 // a self-signature.""
118 // https://tools.ietf.org/html/rfc4880#section-5.2.3.6
119 KeyLifetimeSecs uint32
120 // "The validity period of the signature. This is the number of seconds
121 // after the signature creation time that the signature expires. If
122 // this is not present or has a value of zero, it never expires."
123 // https://tools.ietf.org/html/rfc4880#section-5.2.3.10
124 SigLifetimeSecs uint32
125 // SigningKeyId is used to specify the signing key to use (by Key ID).
126 // By default, the signing key is selected automatically, preferring
127 // signing subkeys if available.
128 SigningKeyId uint64
129 // SigningIdentity is used to specify a user ID (packet Signer's User ID, type 28)
130 // when producing a generic certification signature onto an existing user ID.
131 // The identity must be present in the signer Entity.
132 SigningIdentity string
133 // InsecureAllowUnauthenticatedMessages controls, whether it is tolerated to read
134 // encrypted messages without Modification Detection Code (MDC).
135 // MDC is mandated by the IETF OpenPGP Crypto Refresh draft and has long been implemented
136 // in most OpenPGP implementations. Messages without MDC are considered unnecessarily
137 // insecure and should be prevented whenever possible.
138 // In case one needs to deal with messages from very old OpenPGP implementations, there
139 // might be no other way than to tolerate the missing MDC. Setting this flag, allows this
140 // mode of operation. It should be considered a measure of last resort.
141 InsecureAllowUnauthenticatedMessages bool
142 // InsecureAllowDecryptionWithSigningKeys allows decryption with keys marked as signing keys in the v2 API.
143 // This setting is potentially insecure, but it is needed as some libraries
144 // ignored key flags when selecting a key for encryption.
145 // Not relevant for the v1 API, as all keys were allowed in decryption.
146 InsecureAllowDecryptionWithSigningKeys bool
147 // KnownNotations is a map of Notation Data names to bools, which controls
148 // the notation names that are allowed to be present in critical Notation Data
149 // signature subpackets.
150 KnownNotations map[string]bool
151 // SignatureNotations is a list of Notations to be added to any signatures.
152 SignatureNotations []*Notation
153 // CheckIntendedRecipients controls, whether the OpenPGP Intended Recipient Fingerprint feature
154 // should be enabled for encryption and decryption.
155 // (See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-intended-recipient-fingerpr).
156 // When the flag is set, encryption produces Intended Recipient Fingerprint signature sub-packets and decryption
157 // checks whether the key it was encrypted to is one of the included fingerprints in the signature.
158 // If the flag is disabled, no Intended Recipient Fingerprint sub-packets are created or checked.
159 // The default behavior, when the config or flag is nil, is to enable the feature.
160 CheckIntendedRecipients *bool
161 // CacheSessionKey controls if decryption should return the session key used for decryption.
162 // If the flag is set, the session key is cached in the message details struct.
163 CacheSessionKey bool
164 // CheckPacketSequence is a flag that controls if the pgp message reader should strictly check
165 // that the packet sequence conforms with the grammar mandated by rfc4880.
166 // The default behavior, when the config or flag is nil, is to check the packet sequence.
167 CheckPacketSequence *bool
168 // NonDeterministicSignaturesViaNotation is a flag to enable randomization of signatures.
169 // If true, a salt notation is used to randomize signatures generated by v4 and v5 keys
170 // (v6 signatures are always non-deterministic, by design).
171 // This protects EdDSA signatures from potentially leaking the secret key in case of faults (i.e. bitflips) which, in principle, could occur
172 // during the signing computation. It is added to signatures of any algo for simplicity, and as it may also serve as protection in case of
173 // weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks.
174 // The default behavior, when the config or flag is nil, is to enable the feature.
175 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
181}
182
183func (c *Config) Random() io.Reader {
184 if c == nil || c.Rand == nil {
185 return rand.Reader
186 }
187 return c.Rand
188}
189
190func (c *Config) Hash() crypto.Hash {
191 if c == nil || uint(c.DefaultHash) == 0 {
192 return crypto.SHA256
193 }
194 return c.DefaultHash
195}
196
197func (c *Config) Cipher() CipherFunction {
198 if c == nil || uint8(c.DefaultCipher) == 0 {
199 return CipherAES128
200 }
201 return c.DefaultCipher
202}
203
204func (c *Config) Now() time.Time {
205 if c == nil || c.Time == nil {
206 return time.Now().Truncate(time.Second)
207 }
208 return c.Time().Truncate(time.Second)
209}
210
211// KeyLifetime returns the validity period of the key.
212func (c *Config) KeyLifetime() uint32 {
213 if c == nil {
214 return 0
215 }
216 return c.KeyLifetimeSecs
217}
218
219// SigLifetime returns the validity period of the signature.
220func (c *Config) SigLifetime() uint32 {
221 if c == nil {
222 return 0
223 }
224 return c.SigLifetimeSecs
225}
226
227func (c *Config) Compression() CompressionAlgo {
228 if c == nil {
229 return CompressionNone
230 }
231 return c.DefaultCompressionAlgo
232}
233
234func (c *Config) RSAModulusBits() int {
235 if c == nil || c.RSABits == 0 {
236 return 2048
237 }
238 return c.RSABits
239}
240
241func (c *Config) PublicKeyAlgorithm() PublicKeyAlgorithm {
242 if c == nil || c.Algorithm == 0 {
243 return PubKeyAlgoRSA
244 }
245 return c.Algorithm
246}
247
248func (c *Config) CurveName() Curve {
249 if c == nil || c.Curve == "" {
250 return Curve25519
251 }
252 return c.Curve
253}
254
255// Deprecated: The hash iterations should now be queried via the S2K() method.
256func (c *Config) PasswordHashIterations() int {
257 if c == nil || c.S2KCount == 0 {
258 return 0
259 }
260 return c.S2KCount
261}
262
263func (c *Config) S2K() *s2k.Config {
264 if c == nil {
265 return nil
266 }
267 // for backwards compatibility
268 if c.S2KCount > 0 && c.S2KConfig == nil {
269 return &s2k.Config{
270 S2KCount: c.S2KCount,
271 }
272 }
273 return c.S2KConfig
274}
275
276func (c *Config) AEAD() *AEADConfig {
277 if c == nil {
278 return nil
279 }
280 return c.AEADConfig
281}
282
283func (c *Config) SigningKey() uint64 {
284 if c == nil {
285 return 0
286 }
287 return c.SigningKeyId
288}
289
290func (c *Config) SigningUserId() string {
291 if c == nil {
292 return ""
293 }
294 return c.SigningIdentity
295}
296
297func (c *Config) AllowUnauthenticatedMessages() bool {
298 if c == nil {
299 return false
300 }
301 return c.InsecureAllowUnauthenticatedMessages
302}
303
304func (c *Config) AllowDecryptionWithSigningKeys() bool {
305 if c == nil {
306 return false
307 }
308 return c.InsecureAllowDecryptionWithSigningKeys
309}
310
311func (c *Config) KnownNotation(notationName string) bool {
312 if c == nil {
313 return false
314 }
315 return c.KnownNotations[notationName]
316}
317
318func (c *Config) Notations() []*Notation {
319 if c == nil {
320 return nil
321 }
322 return c.SignatureNotations
323}
324
325func (c *Config) V6() bool {
326 if c == nil {
327 return false
328 }
329 return c.V6Keys
330}
331
332func (c *Config) IntendedRecipients() bool {
333 if c == nil || c.CheckIntendedRecipients == nil {
334 return true
335 }
336 return *c.CheckIntendedRecipients
337}
338
339func (c *Config) RetrieveSessionKey() bool {
340 if c == nil {
341 return false
342 }
343 return c.CacheSessionKey
344}
345
346func (c *Config) MinimumRSABits() uint16 {
347 if c == nil || c.MinRSABits == 0 {
348 return 2047
349 }
350 return c.MinRSABits
351}
352
353func (c *Config) RejectPublicKeyAlgorithm(alg PublicKeyAlgorithm) bool {
354 var rejectedAlgorithms map[PublicKeyAlgorithm]bool
355 if c == nil || c.RejectPublicKeyAlgorithms == nil {
356 // Default
357 rejectedAlgorithms = defaultRejectPublicKeyAlgorithms
358 } else {
359 rejectedAlgorithms = c.RejectPublicKeyAlgorithms
360 }
361 return rejectedAlgorithms[alg]
362}
363
364func (c *Config) RejectHashAlgorithm(hash crypto.Hash) bool {
365 var rejectedAlgorithms map[crypto.Hash]bool
366 if c == nil || c.RejectHashAlgorithms == nil {
367 // Default
368 rejectedAlgorithms = defaultRejectHashAlgorithms
369 } else {
370 rejectedAlgorithms = c.RejectHashAlgorithms
371 }
372 return rejectedAlgorithms[hash]
373}
374
375func (c *Config) RejectMessageHashAlgorithm(hash crypto.Hash) bool {
376 var rejectedAlgorithms map[crypto.Hash]bool
377 if c == nil || c.RejectMessageHashAlgorithms == nil {
378 // Default
379 rejectedAlgorithms = defaultRejectMessageHashAlgorithms
380 } else {
381 rejectedAlgorithms = c.RejectMessageHashAlgorithms
382 }
383 return rejectedAlgorithms[hash]
384}
385
386func (c *Config) RejectCurve(curve Curve) bool {
387 var rejectedCurve map[Curve]bool
388 if c == nil || c.RejectCurves == nil {
389 // Default
390 rejectedCurve = defaultRejectCurves
391 } else {
392 rejectedCurve = c.RejectCurves
393 }
394 return rejectedCurve[curve]
395}
396
397func (c *Config) StrictPacketSequence() bool {
398 if c == nil || c.CheckPacketSequence == nil {
399 return true
400 }
401 return *c.CheckPacketSequence
402}
403
404func (c *Config) RandomizeSignaturesViaNotation() bool {
405 if c == nil || c.NonDeterministicSignaturesViaNotation == nil {
406 return true
407 }
408 return *c.NonDeterministicSignaturesViaNotation
409}
410
411func (c *Config) AllowAllKeyFlagsWhenMissing() bool {
412 if c == nil {
413 return false
414 }
415 return c.InsecureAllowAllKeyFlagsWhenMissing
416}
417
418// BoolPointer is a helper function to set a boolean pointer in the Config.
419// e.g., config.CheckPacketSequence = BoolPointer(true)
420func BoolPointer(value bool) *bool {
421 return &value
422}