main
Raw Download raw file
  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}