~ubuntu-branches/ubuntu/saucy/juju-core/saucy-proposed

« back to all changes in this revision

Viewing changes to src/code.google.com/p/go.crypto/openpgp/read.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-07-11 17:18:27 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20130711171827-vjqkg40r0dlf7ys2
Tags: 1.11.2-0ubuntu1
* New upstream release.
* Make juju-core the default juju (LP: #1190634):
  - d/control: Add virtual package juju -> juju-core.
  - d/juju-core.postinst.in: Bump priority of alternatives over that of
    python juju packages.
* Enable for all architectures (LP: #1172505):
  - d/control: Version BD on golang-go to >= 2:1.1.1 to ensure CGO
    support for non-x86 archs, make juju-core Arch: any.
  - d/README.source: Dropped - no longer required.
* d/watch: Updated for new upstream tarball naming.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
6
package openpgp
 
7
 
 
8
import (
 
9
        "code.google.com/p/go.crypto/openpgp/armor"
 
10
        "code.google.com/p/go.crypto/openpgp/errors"
 
11
        "code.google.com/p/go.crypto/openpgp/packet"
 
12
        "crypto"
 
13
        _ "crypto/sha256"
 
14
        "hash"
 
15
        "io"
 
16
        "strconv"
 
17
)
 
18
 
 
19
// SignatureType is the armor type for a PGP signature.
 
20
var SignatureType = "PGP SIGNATURE"
 
21
 
 
22
// readArmored reads an armored block with the given type.
 
23
func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) {
 
24
        block, err := armor.Decode(r)
 
25
        if err != nil {
 
26
                return
 
27
        }
 
28
 
 
29
        if block.Type != expectedType {
 
30
                return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
 
31
        }
 
32
 
 
33
        return block.Body, nil
 
34
}
 
35
 
 
36
// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
 
37
// signed message.
 
38
type MessageDetails struct {
 
39
        IsEncrypted              bool                // true if the message was encrypted.
 
40
        EncryptedToKeyIds        []uint64            // the list of recipient key ids.
 
41
        IsSymmetricallyEncrypted bool                // true if a passphrase could have decrypted the message.
 
42
        DecryptedWith            Key                 // the private key used to decrypt the message, if any.
 
43
        IsSigned                 bool                // true if the message is signed.
 
44
        SignedByKeyId            uint64              // the key id of the signer, if any.
 
45
        SignedBy                 *Key                // the key of the signer, if available.
 
46
        LiteralData              *packet.LiteralData // the metadata of the contents
 
47
        UnverifiedBody           io.Reader           // the contents of the message.
 
48
 
 
49
        // If IsSigned is true and SignedBy is non-zero then the signature will
 
50
        // be verified as UnverifiedBody is read. The signature cannot be
 
51
        // checked until the whole of UnverifiedBody is read so UnverifiedBody
 
52
        // must be consumed until EOF before the data can trusted. Even if a
 
53
        // message isn't signed (or the signer is unknown) the data may contain
 
54
        // an authentication code that is only checked once UnverifiedBody has
 
55
        // been consumed. Once EOF has been seen, the following fields are
 
56
        // valid. (An authentication code failure is reported as a
 
57
        // SignatureError error when reading from UnverifiedBody.)
 
58
        SignatureError error             // nil if the signature is good.
 
59
        Signature      *packet.Signature // the signature packet itself.
 
60
 
 
61
        decrypted io.ReadCloser
 
62
}
 
63
 
 
64
// A PromptFunction is used as a callback by functions that may need to decrypt
 
65
// a private key, or prompt for a passphrase. It is called with a list of
 
66
// acceptable, encrypted private keys and a boolean that indicates whether a
 
67
// passphrase is usable. It should either decrypt a private key or return a
 
68
// passphrase to try. If the decrypted private key or given passphrase isn't
 
69
// correct, the function will be called again, forever. Any error returned will
 
70
// be passed up.
 
71
type PromptFunction func(keys []Key, symmetric bool) ([]byte, error)
 
72
 
 
73
// A keyEnvelopePair is used to store a private key with the envelope that
 
74
// contains a symmetric key, encrypted with that key.
 
75
type keyEnvelopePair struct {
 
76
        key          Key
 
77
        encryptedKey *packet.EncryptedKey
 
78
}
 
79
 
 
80
// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
 
81
// The given KeyRing should contain both public keys (for signature
 
82
// verification) and, possibly encrypted, private keys for decrypting.
 
83
// If config is nil, sensible defaults will be used.
 
84
func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) {
 
85
        var p packet.Packet
 
86
 
 
87
        var symKeys []*packet.SymmetricKeyEncrypted
 
88
        var pubKeys []keyEnvelopePair
 
89
        var se *packet.SymmetricallyEncrypted
 
90
 
 
91
        packets := packet.NewReader(r)
 
92
        md = new(MessageDetails)
 
93
        md.IsEncrypted = true
 
94
 
 
95
        // The message, if encrypted, starts with a number of packets
 
96
        // containing an encrypted decryption key. The decryption key is either
 
97
        // encrypted to a public key, or with a passphrase. This loop
 
98
        // collects these packets.
 
99
ParsePackets:
 
100
        for {
 
101
                p, err = packets.Next()
 
102
                if err != nil {
 
103
                        return nil, err
 
104
                }
 
105
                switch p := p.(type) {
 
106
                case *packet.SymmetricKeyEncrypted:
 
107
                        // This packet contains the decryption key encrypted with a passphrase.
 
108
                        md.IsSymmetricallyEncrypted = true
 
109
                        symKeys = append(symKeys, p)
 
110
                case *packet.EncryptedKey:
 
111
                        // This packet contains the decryption key encrypted to a public key.
 
112
                        md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
 
113
                        switch p.Algo {
 
114
                        case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
 
115
                                break
 
116
                        default:
 
117
                                continue
 
118
                        }
 
119
                        var keys []Key
 
120
                        if p.KeyId == 0 {
 
121
                                keys = keyring.DecryptionKeys()
 
122
                        } else {
 
123
                                keys = keyring.KeysById(p.KeyId)
 
124
                        }
 
125
                        for _, k := range keys {
 
126
                                pubKeys = append(pubKeys, keyEnvelopePair{k, p})
 
127
                        }
 
128
                case *packet.SymmetricallyEncrypted:
 
129
                        se = p
 
130
                        break ParsePackets
 
131
                case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
 
132
                        // This message isn't encrypted.
 
133
                        if len(symKeys) != 0 || len(pubKeys) != 0 {
 
134
                                return nil, errors.StructuralError("key material not followed by encrypted message")
 
135
                        }
 
136
                        packets.Unread(p)
 
137
                        return readSignedMessage(packets, nil, keyring)
 
138
                }
 
139
        }
 
140
 
 
141
        var candidates []Key
 
142
        var decrypted io.ReadCloser
 
143
 
 
144
        // Now that we have the list of encrypted keys we need to decrypt at
 
145
        // least one of them or, if we cannot, we need to call the prompt
 
146
        // function so that it can decrypt a key or give us a passphrase.
 
147
FindKey:
 
148
        for {
 
149
                // See if any of the keys already have a private key available
 
150
                candidates = candidates[:0]
 
151
                candidateFingerprints := make(map[string]bool)
 
152
 
 
153
                for _, pk := range pubKeys {
 
154
                        if pk.key.PrivateKey == nil {
 
155
                                continue
 
156
                        }
 
157
                        if !pk.key.PrivateKey.Encrypted {
 
158
                                if len(pk.encryptedKey.Key) == 0 {
 
159
                                        pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
 
160
                                }
 
161
                                if len(pk.encryptedKey.Key) == 0 {
 
162
                                        continue
 
163
                                }
 
164
                                decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
 
165
                                if err != nil && err != errors.ErrKeyIncorrect {
 
166
                                        return nil, err
 
167
                                }
 
168
                                if decrypted != nil {
 
169
                                        md.DecryptedWith = pk.key
 
170
                                        break FindKey
 
171
                                }
 
172
                        } else {
 
173
                                fpr := string(pk.key.PublicKey.Fingerprint[:])
 
174
                                if v := candidateFingerprints[fpr]; v {
 
175
                                        continue
 
176
                                }
 
177
                                candidates = append(candidates, pk.key)
 
178
                                candidateFingerprints[fpr] = true
 
179
                        }
 
180
                }
 
181
 
 
182
                if len(candidates) == 0 && len(symKeys) == 0 {
 
183
                        return nil, errors.ErrKeyIncorrect
 
184
                }
 
185
 
 
186
                if prompt == nil {
 
187
                        return nil, errors.ErrKeyIncorrect
 
188
                }
 
189
 
 
190
                passphrase, err := prompt(candidates, len(symKeys) != 0)
 
191
                if err != nil {
 
192
                        return nil, err
 
193
                }
 
194
 
 
195
                // Try the symmetric passphrase first
 
196
                if len(symKeys) != 0 && passphrase != nil {
 
197
                        for _, s := range symKeys {
 
198
                                err = s.Decrypt(passphrase)
 
199
                                if err == nil && !s.Encrypted {
 
200
                                        decrypted, err = se.Decrypt(s.CipherFunc, s.Key)
 
201
                                        if err != nil && err != errors.ErrKeyIncorrect {
 
202
                                                return nil, err
 
203
                                        }
 
204
                                        if decrypted != nil {
 
205
                                                break FindKey
 
206
                                        }
 
207
                                }
 
208
 
 
209
                        }
 
210
                }
 
211
        }
 
212
 
 
213
        md.decrypted = decrypted
 
214
        packets.Push(decrypted)
 
215
        return readSignedMessage(packets, md, keyring)
 
216
}
 
217
 
 
218
// readSignedMessage reads a possibly signed message if mdin is non-zero then
 
219
// that structure is updated and returned. Otherwise a fresh MessageDetails is
 
220
// used.
 
221
func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) {
 
222
        if mdin == nil {
 
223
                mdin = new(MessageDetails)
 
224
        }
 
225
        md = mdin
 
226
 
 
227
        var p packet.Packet
 
228
        var h hash.Hash
 
229
        var wrappedHash hash.Hash
 
230
FindLiteralData:
 
231
        for {
 
232
                p, err = packets.Next()
 
233
                if err != nil {
 
234
                        return nil, err
 
235
                }
 
236
                switch p := p.(type) {
 
237
                case *packet.Compressed:
 
238
                        packets.Push(p.Body)
 
239
                case *packet.OnePassSignature:
 
240
                        if !p.IsLast {
 
241
                                return nil, errors.UnsupportedError("nested signatures")
 
242
                        }
 
243
 
 
244
                        h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
 
245
                        if err != nil {
 
246
                                md = nil
 
247
                                return
 
248
                        }
 
249
 
 
250
                        md.IsSigned = true
 
251
                        md.SignedByKeyId = p.KeyId
 
252
                        keys := keyring.KeysById(p.KeyId)
 
253
                        for i, key := range keys {
 
254
                                if key.SelfSignature.FlagsValid && !key.SelfSignature.FlagSign {
 
255
                                        continue
 
256
                                }
 
257
                                md.SignedBy = &keys[i]
 
258
                                break
 
259
                        }
 
260
                case *packet.LiteralData:
 
261
                        md.LiteralData = p
 
262
                        break FindLiteralData
 
263
                }
 
264
        }
 
265
 
 
266
        if md.SignedBy != nil {
 
267
                md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
 
268
        } else if md.decrypted != nil {
 
269
                md.UnverifiedBody = checkReader{md}
 
270
        } else {
 
271
                md.UnverifiedBody = md.LiteralData.Body
 
272
        }
 
273
 
 
274
        return md, nil
 
275
}
 
276
 
 
277
// hashForSignature returns a pair of hashes that can be used to verify a
 
278
// signature. The signature may specify that the contents of the signed message
 
279
// should be preprocessed (i.e. to normalize line endings). Thus this function
 
280
// returns two hashes. The second should be used to hash the message itself and
 
281
// performs any needed preprocessing.
 
282
func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
 
283
        h := hashId.New()
 
284
        if h == nil {
 
285
                return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
 
286
        }
 
287
 
 
288
        switch sigType {
 
289
        case packet.SigTypeBinary:
 
290
                return h, h, nil
 
291
        case packet.SigTypeText:
 
292
                return h, NewCanonicalTextHash(h), nil
 
293
        }
 
294
 
 
295
        return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
 
296
}
 
297
 
 
298
// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
 
299
// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
 
300
// MDC checks.
 
301
type checkReader struct {
 
302
        md *MessageDetails
 
303
}
 
304
 
 
305
func (cr checkReader) Read(buf []byte) (n int, err error) {
 
306
        n, err = cr.md.LiteralData.Body.Read(buf)
 
307
        if err == io.EOF {
 
308
                mdcErr := cr.md.decrypted.Close()
 
309
                if mdcErr != nil {
 
310
                        err = mdcErr
 
311
                }
 
312
        }
 
313
        return
 
314
}
 
315
 
 
316
// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
 
317
// the data as it is read. When it sees an EOF from the underlying io.Reader
 
318
// it parses and checks a trailing Signature packet and triggers any MDC checks.
 
319
type signatureCheckReader struct {
 
320
        packets        *packet.Reader
 
321
        h, wrappedHash hash.Hash
 
322
        md             *MessageDetails
 
323
}
 
324
 
 
325
func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
 
326
        n, err = scr.md.LiteralData.Body.Read(buf)
 
327
        scr.wrappedHash.Write(buf[:n])
 
328
        if err == io.EOF {
 
329
                var p packet.Packet
 
330
                p, scr.md.SignatureError = scr.packets.Next()
 
331
                if scr.md.SignatureError != nil {
 
332
                        return
 
333
                }
 
334
 
 
335
                var ok bool
 
336
                if scr.md.Signature, ok = p.(*packet.Signature); !ok {
 
337
                        scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
 
338
                        return
 
339
                }
 
340
 
 
341
                scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
 
342
 
 
343
                // The SymmetricallyEncrypted packet, if any, might have an
 
344
                // unsigned hash of its own. In order to check this we need to
 
345
                // close that Reader.
 
346
                if scr.md.decrypted != nil {
 
347
                        mdcErr := scr.md.decrypted.Close()
 
348
                        if mdcErr != nil {
 
349
                                err = mdcErr
 
350
                        }
 
351
                }
 
352
        }
 
353
        return
 
354
}
 
355
 
 
356
// CheckDetachedSignature takes a signed file and a detached signature and
 
357
// returns the signer if the signature is valid. If the signer isn't known,
 
358
// ErrUnknownIssuer is returned.
 
359
func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
 
360
        p, err := packet.Read(signature)
 
361
        if err != nil {
 
362
                return
 
363
        }
 
364
 
 
365
        sig, ok := p.(*packet.Signature)
 
366
        if !ok {
 
367
                return nil, errors.StructuralError("non signature packet found")
 
368
        }
 
369
 
 
370
        if sig.IssuerKeyId == nil {
 
371
                return nil, errors.StructuralError("signature doesn't have an issuer")
 
372
        }
 
373
 
 
374
        keys := keyring.KeysById(*sig.IssuerKeyId)
 
375
        if len(keys) == 0 {
 
376
                return nil, errors.ErrUnknownIssuer
 
377
        }
 
378
 
 
379
        h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
 
380
        if err != nil {
 
381
                return
 
382
        }
 
383
 
 
384
        _, err = io.Copy(wrappedHash, signed)
 
385
        if err != nil && err != io.EOF {
 
386
                return
 
387
        }
 
388
 
 
389
        for _, key := range keys {
 
390
                if key.SelfSignature.FlagsValid && !key.SelfSignature.FlagSign {
 
391
                        continue
 
392
                }
 
393
                err = key.PublicKey.VerifySignature(h, sig)
 
394
                if err == nil {
 
395
                        return key.Entity, nil
 
396
                }
 
397
        }
 
398
 
 
399
        if err != nil {
 
400
                return
 
401
        }
 
402
 
 
403
        return nil, errors.ErrUnknownIssuer
 
404
}
 
405
 
 
406
// CheckArmoredDetachedSignature performs the same actions as
 
407
// CheckDetachedSignature but expects the signature to be armored.
 
408
func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
 
409
        body, err := readArmored(signature, SignatureType)
 
410
        if err != nil {
 
411
                return
 
412
        }
 
413
 
 
414
        return CheckDetachedSignature(keyring, signed, body)
 
415
}