main
1// Copyright 2011 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
5// Package openpgp implements high level operations on OpenPGP messages.
6package openpgp // import "github.com/ProtonMail/go-crypto/openpgp"
7
8import (
9 "crypto"
10 _ "crypto/sha256"
11 _ "crypto/sha512"
12 "hash"
13 "io"
14 "strconv"
15
16 "github.com/ProtonMail/go-crypto/openpgp/armor"
17 "github.com/ProtonMail/go-crypto/openpgp/errors"
18 "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
19 "github.com/ProtonMail/go-crypto/openpgp/packet"
20 _ "golang.org/x/crypto/sha3"
21)
22
23// SignatureType is the armor type for a PGP signature.
24var SignatureType = "PGP SIGNATURE"
25
26// readArmored reads an armored block with the given type.
27func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) {
28 block, err := armor.Decode(r)
29 if err != nil {
30 return
31 }
32
33 if block.Type != expectedType {
34 return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
35 }
36
37 return block.Body, nil
38}
39
40// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
41// signed message.
42type MessageDetails struct {
43 IsEncrypted bool // true if the message was encrypted.
44 EncryptedToKeyIds []uint64 // the list of recipient key ids.
45 IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message.
46 DecryptedWith Key // the private key used to decrypt the message, if any.
47 IsSigned bool // true if the message is signed.
48 SignedByKeyId uint64 // the key id of the signer, if any.
49 SignedByFingerprint []byte // the key fingerprint of the signer, if any.
50 SignedBy *Key // the key of the signer, if available.
51 LiteralData *packet.LiteralData // the metadata of the contents
52 UnverifiedBody io.Reader // the contents of the message.
53
54 // If IsSigned is true and SignedBy is non-zero then the signature will
55 // be verified as UnverifiedBody is read. The signature cannot be
56 // checked until the whole of UnverifiedBody is read so UnverifiedBody
57 // must be consumed until EOF before the data can be trusted. Even if a
58 // message isn't signed (or the signer is unknown) the data may contain
59 // an authentication code that is only checked once UnverifiedBody has
60 // been consumed. Once EOF has been seen, the following fields are
61 // valid. (An authentication code failure is reported as a
62 // SignatureError error when reading from UnverifiedBody.)
63 Signature *packet.Signature // the signature packet itself.
64 SignatureError error // nil if the signature is good.
65 UnverifiedSignatures []*packet.Signature // all other unverified signature packets.
66
67 decrypted io.ReadCloser
68}
69
70// A PromptFunction is used as a callback by functions that may need to decrypt
71// a private key, or prompt for a passphrase. It is called with a list of
72// acceptable, encrypted private keys and a boolean that indicates whether a
73// passphrase is usable. It should either decrypt a private key or return a
74// passphrase to try. If the decrypted private key or given passphrase isn't
75// correct, the function will be called again, forever. Any error returned will
76// be passed up.
77type PromptFunction func(keys []Key, symmetric bool) ([]byte, error)
78
79// A keyEnvelopePair is used to store a private key with the envelope that
80// contains a symmetric key, encrypted with that key.
81type keyEnvelopePair struct {
82 key Key
83 encryptedKey *packet.EncryptedKey
84}
85
86// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
87// The given KeyRing should contain both public keys (for signature
88// verification) and, possibly encrypted, private keys for decrypting.
89// If config is nil, sensible defaults will be used.
90func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) {
91 var p packet.Packet
92
93 var symKeys []*packet.SymmetricKeyEncrypted
94 var pubKeys []keyEnvelopePair
95 // Integrity protected encrypted packet: SymmetricallyEncrypted or AEADEncrypted
96 var edp packet.EncryptedDataPacket
97
98 packets := packet.NewReader(r)
99 md = new(MessageDetails)
100 md.IsEncrypted = true
101
102 // The message, if encrypted, starts with a number of packets
103 // containing an encrypted decryption key. The decryption key is either
104 // encrypted to a public key, or with a passphrase. This loop
105 // collects these packets.
106ParsePackets:
107 for {
108 p, err = packets.Next()
109 if err != nil {
110 return nil, err
111 }
112 switch p := p.(type) {
113 case *packet.SymmetricKeyEncrypted:
114 // This packet contains the decryption key encrypted with a passphrase.
115 md.IsSymmetricallyEncrypted = true
116 symKeys = append(symKeys, p)
117 case *packet.EncryptedKey:
118 // This packet contains the decryption key encrypted to a public key.
119 md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
120 switch p.Algo {
121 case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH, packet.PubKeyAlgoX25519, packet.PubKeyAlgoX448:
122 break
123 default:
124 continue
125 }
126 if keyring != nil {
127 var keys []Key
128 if p.KeyId == 0 {
129 keys = keyring.DecryptionKeys()
130 } else {
131 keys = keyring.KeysById(p.KeyId)
132 }
133 for _, k := range keys {
134 pubKeys = append(pubKeys, keyEnvelopePair{k, p})
135 }
136 }
137 case *packet.SymmetricallyEncrypted:
138 if !p.IntegrityProtected && !config.AllowUnauthenticatedMessages() {
139 return nil, errors.UnsupportedError("message is not integrity protected")
140 }
141 edp = p
142 break ParsePackets
143 case *packet.AEADEncrypted:
144 edp = p
145 break ParsePackets
146 case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
147 // This message isn't encrypted.
148 if len(symKeys) != 0 || len(pubKeys) != 0 {
149 return nil, errors.StructuralError("key material not followed by encrypted message")
150 }
151 packets.Unread(p)
152 return readSignedMessage(packets, nil, keyring, config)
153 }
154 }
155
156 var candidates []Key
157 var decrypted io.ReadCloser
158
159 // Now that we have the list of encrypted keys we need to decrypt at
160 // least one of them or, if we cannot, we need to call the prompt
161 // function so that it can decrypt a key or give us a passphrase.
162FindKey:
163 for {
164 // See if any of the keys already have a private key available
165 candidates = candidates[:0]
166 candidateFingerprints := make(map[string]bool)
167
168 for _, pk := range pubKeys {
169 if pk.key.PrivateKey == nil {
170 continue
171 }
172 if !pk.key.PrivateKey.Encrypted {
173 if len(pk.encryptedKey.Key) == 0 {
174 errDec := pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
175 if errDec != nil {
176 continue
177 }
178 }
179 // Try to decrypt symmetrically encrypted
180 decrypted, err = edp.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
181 if err != nil && err != errors.ErrKeyIncorrect {
182 return nil, err
183 }
184 if decrypted != nil {
185 md.DecryptedWith = pk.key
186 break FindKey
187 }
188 } else {
189 fpr := string(pk.key.PublicKey.Fingerprint[:])
190 if v := candidateFingerprints[fpr]; v {
191 continue
192 }
193 candidates = append(candidates, pk.key)
194 candidateFingerprints[fpr] = true
195 }
196 }
197
198 if len(candidates) == 0 && len(symKeys) == 0 {
199 return nil, errors.ErrKeyIncorrect
200 }
201
202 if prompt == nil {
203 return nil, errors.ErrKeyIncorrect
204 }
205
206 passphrase, err := prompt(candidates, len(symKeys) != 0)
207 if err != nil {
208 return nil, err
209 }
210
211 // Try the symmetric passphrase first
212 if len(symKeys) != 0 && passphrase != nil {
213 for _, s := range symKeys {
214 key, cipherFunc, err := s.Decrypt(passphrase)
215 // In v4, on wrong passphrase, session key decryption is very likely to result in an invalid cipherFunc:
216 // only for < 5% of cases we will proceed to decrypt the data
217 if err == nil {
218 decrypted, err = edp.Decrypt(cipherFunc, key)
219 if err != nil {
220 return nil, err
221 }
222 if decrypted != nil {
223 break FindKey
224 }
225 }
226 }
227 }
228 }
229
230 md.decrypted = decrypted
231 if err := packets.Push(decrypted); err != nil {
232 return nil, err
233 }
234 mdFinal, sensitiveParsingErr := readSignedMessage(packets, md, keyring, config)
235 if sensitiveParsingErr != nil {
236 return nil, errors.HandleSensitiveParsingError(sensitiveParsingErr, md.decrypted != nil)
237 }
238 return mdFinal, nil
239}
240
241// readSignedMessage reads a possibly signed message if mdin is non-zero then
242// that structure is updated and returned. Otherwise a fresh MessageDetails is
243// used.
244func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing, config *packet.Config) (md *MessageDetails, err error) {
245 if mdin == nil {
246 mdin = new(MessageDetails)
247 }
248 md = mdin
249
250 var p packet.Packet
251 var h hash.Hash
252 var wrappedHash hash.Hash
253 var prevLast bool
254FindLiteralData:
255 for {
256 p, err = packets.Next()
257 if err != nil {
258 return nil, err
259 }
260 switch p := p.(type) {
261 case *packet.Compressed:
262 if err := packets.Push(p.Body); err != nil {
263 return nil, err
264 }
265 case *packet.OnePassSignature:
266 if prevLast {
267 return nil, errors.UnsupportedError("nested signature packets")
268 }
269
270 if p.IsLast {
271 prevLast = true
272 }
273
274 h, wrappedHash, err = hashForSignature(p.Hash, p.SigType, p.Salt)
275 if err != nil {
276 md.SignatureError = err
277 }
278
279 md.IsSigned = true
280 if p.Version == 6 {
281 md.SignedByFingerprint = p.KeyFingerprint
282 }
283 md.SignedByKeyId = p.KeyId
284
285 if keyring != nil {
286 keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
287 if len(keys) > 0 {
288 md.SignedBy = &keys[0]
289 }
290 }
291 case *packet.LiteralData:
292 md.LiteralData = p
293 break FindLiteralData
294 }
295 }
296
297 if md.IsSigned && md.SignatureError == nil {
298 md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md, config}
299 } else if md.decrypted != nil {
300 md.UnverifiedBody = &checkReader{md, false}
301 } else {
302 md.UnverifiedBody = md.LiteralData.Body
303 }
304
305 return md, nil
306}
307
308func wrapHashForSignature(hashFunc hash.Hash, sigType packet.SignatureType) (hash.Hash, error) {
309 switch sigType {
310 case packet.SigTypeBinary:
311 return hashFunc, nil
312 case packet.SigTypeText:
313 return NewCanonicalTextHash(hashFunc), nil
314 }
315 return nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
316}
317
318// hashForSignature returns a pair of hashes that can be used to verify a
319// signature. The signature may specify that the contents of the signed message
320// should be preprocessed (i.e. to normalize line endings). Thus this function
321// returns two hashes. The second should be used to hash the message itself and
322// performs any needed preprocessing.
323func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType, sigSalt []byte) (hash.Hash, hash.Hash, error) {
324 if _, ok := algorithm.HashToHashIdWithSha1(hashFunc); !ok {
325 return nil, nil, errors.UnsupportedError("unsupported hash function")
326 }
327 if !hashFunc.Available() {
328 return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashFunc)))
329 }
330 h := hashFunc.New()
331 if sigSalt != nil {
332 h.Write(sigSalt)
333 }
334 wrappedHash, err := wrapHashForSignature(h, sigType)
335 if err != nil {
336 return nil, nil, err
337 }
338 switch sigType {
339 case packet.SigTypeBinary:
340 return h, wrappedHash, nil
341 case packet.SigTypeText:
342 return h, wrappedHash, nil
343 }
344 return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
345}
346
347// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
348// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
349// MDC checks.
350type checkReader struct {
351 md *MessageDetails
352 checked bool
353}
354
355func (cr *checkReader) Read(buf []byte) (int, error) {
356 n, sensitiveParsingError := cr.md.LiteralData.Body.Read(buf)
357 if sensitiveParsingError == io.EOF {
358 if cr.checked {
359 // Only check once
360 return n, io.EOF
361 }
362 mdcErr := cr.md.decrypted.Close()
363 if mdcErr != nil {
364 return n, mdcErr
365 }
366 cr.checked = true
367 return n, io.EOF
368 }
369
370 if sensitiveParsingError != nil {
371 return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true)
372 }
373
374 return n, nil
375}
376
377// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
378// the data as it is read. When it sees an EOF from the underlying io.Reader
379// it parses and checks a trailing Signature packet and triggers any MDC checks.
380type signatureCheckReader struct {
381 packets *packet.Reader
382 h, wrappedHash hash.Hash
383 md *MessageDetails
384 config *packet.Config
385}
386
387func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
388 n, sensitiveParsingError := scr.md.LiteralData.Body.Read(buf)
389
390 // Hash only if required
391 if scr.md.SignedBy != nil {
392 scr.wrappedHash.Write(buf[:n])
393 }
394
395 readsDecryptedData := scr.md.decrypted != nil
396 if sensitiveParsingError == io.EOF {
397 var p packet.Packet
398 var readError error
399 var sig *packet.Signature
400
401 p, readError = scr.packets.Next()
402 for readError == nil {
403 var ok bool
404 if sig, ok = p.(*packet.Signature); ok {
405 if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
406 sig.Metadata = scr.md.LiteralData
407 }
408
409 // If signature KeyID matches
410 if scr.md.SignedBy != nil && *sig.IssuerKeyId == scr.md.SignedByKeyId {
411 key := scr.md.SignedBy
412 signatureError := key.PublicKey.VerifySignature(scr.h, sig)
413 if signatureError == nil {
414 signatureError = checkMessageSignatureDetails(key, sig, scr.config)
415 }
416 scr.md.Signature = sig
417 scr.md.SignatureError = signatureError
418 } else {
419 scr.md.UnverifiedSignatures = append(scr.md.UnverifiedSignatures, sig)
420 }
421 }
422
423 p, readError = scr.packets.Next()
424 }
425
426 if scr.md.SignedBy != nil && scr.md.Signature == nil {
427 if scr.md.UnverifiedSignatures == nil {
428 scr.md.SignatureError = errors.StructuralError("LiteralData not followed by signature")
429 } else {
430 scr.md.SignatureError = errors.StructuralError("No matching signature found")
431 }
432 }
433
434 // The SymmetricallyEncrypted packet, if any, might have an
435 // unsigned hash of its own. In order to check this we need to
436 // close that Reader.
437 if scr.md.decrypted != nil {
438 if sensitiveParsingError := scr.md.decrypted.Close(); sensitiveParsingError != nil {
439 return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true)
440 }
441 }
442 return n, io.EOF
443 }
444
445 if sensitiveParsingError != nil {
446 return n, errors.HandleSensitiveParsingError(sensitiveParsingError, readsDecryptedData)
447 }
448
449 return n, nil
450}
451
452// VerifyDetachedSignature takes a signed file and a detached signature and
453// returns the signature packet and the entity the signature was signed by,
454// if any, and a possible signature verification error.
455// If the signer isn't known, ErrUnknownIssuer is returned.
456func VerifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
457 return verifyDetachedSignature(keyring, signed, signature, nil, false, config)
458}
459
460// VerifyDetachedSignatureAndHash performs the same actions as
461// VerifyDetachedSignature and checks that the expected hash functions were used.
462func VerifyDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
463 return verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config)
464}
465
466// CheckDetachedSignature takes a signed file and a detached signature and
467// returns the entity the signature was signed by, if any, and a possible
468// signature verification error. If the signer isn't known,
469// ErrUnknownIssuer is returned.
470func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) {
471 _, signer, err = verifyDetachedSignature(keyring, signed, signature, nil, false, config)
472 return
473}
474
475// CheckDetachedSignatureAndHash performs the same actions as
476// CheckDetachedSignature and checks that the expected hash functions were used.
477func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (signer *Entity, err error) {
478 _, signer, err = verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config)
479 return
480}
481
482func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, checkHashes bool, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
483 var issuerKeyId uint64
484 var hashFunc crypto.Hash
485 var sigType packet.SignatureType
486 var keys []Key
487 var p packet.Packet
488
489 packets := packet.NewReader(signature)
490 for {
491 p, err = packets.Next()
492 if err == io.EOF {
493 return nil, nil, errors.ErrUnknownIssuer
494 }
495 if err != nil {
496 return nil, nil, err
497 }
498
499 var ok bool
500 sig, ok = p.(*packet.Signature)
501 if !ok {
502 return nil, nil, errors.StructuralError("non signature packet found")
503 }
504 if sig.IssuerKeyId == nil {
505 return nil, nil, errors.StructuralError("signature doesn't have an issuer")
506 }
507 issuerKeyId = *sig.IssuerKeyId
508 hashFunc = sig.Hash
509 sigType = sig.SigType
510 if checkHashes {
511 matchFound := false
512 // check for hashes
513 for _, expectedHash := range expectedHashes {
514 if hashFunc == expectedHash {
515 matchFound = true
516 break
517 }
518 }
519 if !matchFound {
520 return nil, nil, errors.StructuralError("hash algorithm or salt mismatch with cleartext message headers")
521 }
522 }
523 keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
524 if len(keys) > 0 {
525 break
526 }
527 }
528
529 if len(keys) == 0 {
530 panic("unreachable")
531 }
532
533 h, err := sig.PrepareVerify()
534 if err != nil {
535 return nil, nil, err
536 }
537 wrappedHash, err := wrapHashForSignature(h, sigType)
538 if err != nil {
539 return nil, nil, err
540 }
541
542 if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF {
543 return nil, nil, err
544 }
545
546 for _, key := range keys {
547 err = key.PublicKey.VerifySignature(h, sig)
548 if err == nil {
549 return sig, key.Entity, checkMessageSignatureDetails(&key, sig, config)
550 }
551 }
552
553 return nil, nil, err
554}
555
556// CheckArmoredDetachedSignature performs the same actions as
557// CheckDetachedSignature but expects the signature to be armored.
558func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) {
559 body, err := readArmored(signature, SignatureType)
560 if err != nil {
561 return
562 }
563
564 return CheckDetachedSignature(keyring, signed, body, config)
565}
566
567// checkMessageSignatureDetails returns an error if:
568// - The signature (or one of the binding signatures mentioned below)
569// has a unknown critical notation data subpacket
570// - The primary key of the signing entity is revoked
571// - The primary identity is revoked
572// - The signature is expired
573// - The primary key of the signing entity is expired according to the
574// primary identity binding signature
575//
576// ... or, if the signature was signed by a subkey and:
577// - The signing subkey is revoked
578// - The signing subkey is expired according to the subkey binding signature
579// - The signing subkey binding signature is expired
580// - The signing subkey cross-signature is expired
581//
582// NOTE: The order of these checks is important, as the caller may choose to
583// ignore ErrSignatureExpired or ErrKeyExpired errors, but should never
584// ignore any other errors.
585func checkMessageSignatureDetails(key *Key, signature *packet.Signature, config *packet.Config) error {
586 now := config.Now()
587 primarySelfSignature, primaryIdentity := key.Entity.PrimarySelfSignature()
588 signedBySubKey := key.PublicKey != key.Entity.PrimaryKey
589 sigsToCheck := []*packet.Signature{signature, primarySelfSignature}
590 if signedBySubKey {
591 sigsToCheck = append(sigsToCheck, key.SelfSignature, key.SelfSignature.EmbeddedSignature)
592 }
593 for _, sig := range sigsToCheck {
594 for _, notation := range sig.Notations {
595 if notation.IsCritical && !config.KnownNotation(notation.Name) {
596 return errors.SignatureError("unknown critical notation: " + notation.Name)
597 }
598 }
599 }
600 if key.Entity.Revoked(now) || // primary key is revoked
601 (signedBySubKey && key.Revoked(now)) || // subkey is revoked
602 (primaryIdentity != nil && primaryIdentity.Revoked(now)) { // primary identity is revoked for v4
603 return errors.ErrKeyRevoked
604 }
605 if key.Entity.PrimaryKey.KeyExpired(primarySelfSignature, now) { // primary key is expired
606 return errors.ErrKeyExpired
607 }
608 if signedBySubKey {
609 if key.PublicKey.KeyExpired(key.SelfSignature, now) { // subkey is expired
610 return errors.ErrKeyExpired
611 }
612 }
613 for _, sig := range sigsToCheck {
614 if sig.SigExpired(now) { // any of the relevant signatures are expired
615 return errors.ErrSignatureExpired
616 }
617 }
618 return nil
619}