diff options
Diffstat (limited to 'vendor/golang.org/x/crypto/openpgp/packet/signature.go')
-rw-r--r-- | vendor/golang.org/x/crypto/openpgp/packet/signature.go | 731 |
1 files changed, 731 insertions, 0 deletions
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature.go b/vendor/golang.org/x/crypto/openpgp/packet/signature.go new file mode 100644 index 0000000..6ce0cbe --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/signature.go | |||
@@ -0,0 +1,731 @@ | |||
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 packet | ||
6 | |||
7 | import ( | ||
8 | "bytes" | ||
9 | "crypto" | ||
10 | "crypto/dsa" | ||
11 | "crypto/ecdsa" | ||
12 | "encoding/asn1" | ||
13 | "encoding/binary" | ||
14 | "hash" | ||
15 | "io" | ||
16 | "math/big" | ||
17 | "strconv" | ||
18 | "time" | ||
19 | |||
20 | "golang.org/x/crypto/openpgp/errors" | ||
21 | "golang.org/x/crypto/openpgp/s2k" | ||
22 | ) | ||
23 | |||
24 | const ( | ||
25 | // See RFC 4880, section 5.2.3.21 for details. | ||
26 | KeyFlagCertify = 1 << iota | ||
27 | KeyFlagSign | ||
28 | KeyFlagEncryptCommunications | ||
29 | KeyFlagEncryptStorage | ||
30 | ) | ||
31 | |||
32 | // Signature represents a signature. See RFC 4880, section 5.2. | ||
33 | type Signature struct { | ||
34 | SigType SignatureType | ||
35 | PubKeyAlgo PublicKeyAlgorithm | ||
36 | Hash crypto.Hash | ||
37 | |||
38 | // HashSuffix is extra data that is hashed in after the signed data. | ||
39 | HashSuffix []byte | ||
40 | // HashTag contains the first two bytes of the hash for fast rejection | ||
41 | // of bad signed data. | ||
42 | HashTag [2]byte | ||
43 | CreationTime time.Time | ||
44 | |||
45 | RSASignature parsedMPI | ||
46 | DSASigR, DSASigS parsedMPI | ||
47 | ECDSASigR, ECDSASigS parsedMPI | ||
48 | |||
49 | // rawSubpackets contains the unparsed subpackets, in order. | ||
50 | rawSubpackets []outputSubpacket | ||
51 | |||
52 | // The following are optional so are nil when not included in the | ||
53 | // signature. | ||
54 | |||
55 | SigLifetimeSecs, KeyLifetimeSecs *uint32 | ||
56 | PreferredSymmetric, PreferredHash, PreferredCompression []uint8 | ||
57 | IssuerKeyId *uint64 | ||
58 | IsPrimaryId *bool | ||
59 | |||
60 | // FlagsValid is set if any flags were given. See RFC 4880, section | ||
61 | // 5.2.3.21 for details. | ||
62 | FlagsValid bool | ||
63 | FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool | ||
64 | |||
65 | // RevocationReason is set if this signature has been revoked. | ||
66 | // See RFC 4880, section 5.2.3.23 for details. | ||
67 | RevocationReason *uint8 | ||
68 | RevocationReasonText string | ||
69 | |||
70 | // MDC is set if this signature has a feature packet that indicates | ||
71 | // support for MDC subpackets. | ||
72 | MDC bool | ||
73 | |||
74 | // EmbeddedSignature, if non-nil, is a signature of the parent key, by | ||
75 | // this key. This prevents an attacker from claiming another's signing | ||
76 | // subkey as their own. | ||
77 | EmbeddedSignature *Signature | ||
78 | |||
79 | outSubpackets []outputSubpacket | ||
80 | } | ||
81 | |||
82 | func (sig *Signature) parse(r io.Reader) (err error) { | ||
83 | // RFC 4880, section 5.2.3 | ||
84 | var buf [5]byte | ||
85 | _, err = readFull(r, buf[:1]) | ||
86 | if err != nil { | ||
87 | return | ||
88 | } | ||
89 | if buf[0] != 4 { | ||
90 | err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) | ||
91 | return | ||
92 | } | ||
93 | |||
94 | _, err = readFull(r, buf[:5]) | ||
95 | if err != nil { | ||
96 | return | ||
97 | } | ||
98 | sig.SigType = SignatureType(buf[0]) | ||
99 | sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) | ||
100 | switch sig.PubKeyAlgo { | ||
101 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: | ||
102 | default: | ||
103 | err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) | ||
104 | return | ||
105 | } | ||
106 | |||
107 | var ok bool | ||
108 | sig.Hash, ok = s2k.HashIdToHash(buf[2]) | ||
109 | if !ok { | ||
110 | return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) | ||
111 | } | ||
112 | |||
113 | hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) | ||
114 | l := 6 + hashedSubpacketsLength | ||
115 | sig.HashSuffix = make([]byte, l+6) | ||
116 | sig.HashSuffix[0] = 4 | ||
117 | copy(sig.HashSuffix[1:], buf[:5]) | ||
118 | hashedSubpackets := sig.HashSuffix[6:l] | ||
119 | _, err = readFull(r, hashedSubpackets) | ||
120 | if err != nil { | ||
121 | return | ||
122 | } | ||
123 | // See RFC 4880, section 5.2.4 | ||
124 | trailer := sig.HashSuffix[l:] | ||
125 | trailer[0] = 4 | ||
126 | trailer[1] = 0xff | ||
127 | trailer[2] = uint8(l >> 24) | ||
128 | trailer[3] = uint8(l >> 16) | ||
129 | trailer[4] = uint8(l >> 8) | ||
130 | trailer[5] = uint8(l) | ||
131 | |||
132 | err = parseSignatureSubpackets(sig, hashedSubpackets, true) | ||
133 | if err != nil { | ||
134 | return | ||
135 | } | ||
136 | |||
137 | _, err = readFull(r, buf[:2]) | ||
138 | if err != nil { | ||
139 | return | ||
140 | } | ||
141 | unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1]) | ||
142 | unhashedSubpackets := make([]byte, unhashedSubpacketsLength) | ||
143 | _, err = readFull(r, unhashedSubpackets) | ||
144 | if err != nil { | ||
145 | return | ||
146 | } | ||
147 | err = parseSignatureSubpackets(sig, unhashedSubpackets, false) | ||
148 | if err != nil { | ||
149 | return | ||
150 | } | ||
151 | |||
152 | _, err = readFull(r, sig.HashTag[:2]) | ||
153 | if err != nil { | ||
154 | return | ||
155 | } | ||
156 | |||
157 | switch sig.PubKeyAlgo { | ||
158 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: | ||
159 | sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) | ||
160 | case PubKeyAlgoDSA: | ||
161 | sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) | ||
162 | if err == nil { | ||
163 | sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) | ||
164 | } | ||
165 | case PubKeyAlgoECDSA: | ||
166 | sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r) | ||
167 | if err == nil { | ||
168 | sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r) | ||
169 | } | ||
170 | default: | ||
171 | panic("unreachable") | ||
172 | } | ||
173 | return | ||
174 | } | ||
175 | |||
176 | // parseSignatureSubpackets parses subpackets of the main signature packet. See | ||
177 | // RFC 4880, section 5.2.3.1. | ||
178 | func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) { | ||
179 | for len(subpackets) > 0 { | ||
180 | subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) | ||
181 | if err != nil { | ||
182 | return | ||
183 | } | ||
184 | } | ||
185 | |||
186 | if sig.CreationTime.IsZero() { | ||
187 | err = errors.StructuralError("no creation time in signature") | ||
188 | } | ||
189 | |||
190 | return | ||
191 | } | ||
192 | |||
193 | type signatureSubpacketType uint8 | ||
194 | |||
195 | const ( | ||
196 | creationTimeSubpacket signatureSubpacketType = 2 | ||
197 | signatureExpirationSubpacket signatureSubpacketType = 3 | ||
198 | keyExpirationSubpacket signatureSubpacketType = 9 | ||
199 | prefSymmetricAlgosSubpacket signatureSubpacketType = 11 | ||
200 | issuerSubpacket signatureSubpacketType = 16 | ||
201 | prefHashAlgosSubpacket signatureSubpacketType = 21 | ||
202 | prefCompressionSubpacket signatureSubpacketType = 22 | ||
203 | primaryUserIdSubpacket signatureSubpacketType = 25 | ||
204 | keyFlagsSubpacket signatureSubpacketType = 27 | ||
205 | reasonForRevocationSubpacket signatureSubpacketType = 29 | ||
206 | featuresSubpacket signatureSubpacketType = 30 | ||
207 | embeddedSignatureSubpacket signatureSubpacketType = 32 | ||
208 | ) | ||
209 | |||
210 | // parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. | ||
211 | func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { | ||
212 | // RFC 4880, section 5.2.3.1 | ||
213 | var ( | ||
214 | length uint32 | ||
215 | packetType signatureSubpacketType | ||
216 | isCritical bool | ||
217 | ) | ||
218 | switch { | ||
219 | case subpacket[0] < 192: | ||
220 | length = uint32(subpacket[0]) | ||
221 | subpacket = subpacket[1:] | ||
222 | case subpacket[0] < 255: | ||
223 | if len(subpacket) < 2 { | ||
224 | goto Truncated | ||
225 | } | ||
226 | length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192 | ||
227 | subpacket = subpacket[2:] | ||
228 | default: | ||
229 | if len(subpacket) < 5 { | ||
230 | goto Truncated | ||
231 | } | ||
232 | length = uint32(subpacket[1])<<24 | | ||
233 | uint32(subpacket[2])<<16 | | ||
234 | uint32(subpacket[3])<<8 | | ||
235 | uint32(subpacket[4]) | ||
236 | subpacket = subpacket[5:] | ||
237 | } | ||
238 | if length > uint32(len(subpacket)) { | ||
239 | goto Truncated | ||
240 | } | ||
241 | rest = subpacket[length:] | ||
242 | subpacket = subpacket[:length] | ||
243 | if len(subpacket) == 0 { | ||
244 | err = errors.StructuralError("zero length signature subpacket") | ||
245 | return | ||
246 | } | ||
247 | packetType = signatureSubpacketType(subpacket[0] & 0x7f) | ||
248 | isCritical = subpacket[0]&0x80 == 0x80 | ||
249 | subpacket = subpacket[1:] | ||
250 | sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) | ||
251 | switch packetType { | ||
252 | case creationTimeSubpacket: | ||
253 | if !isHashed { | ||
254 | err = errors.StructuralError("signature creation time in non-hashed area") | ||
255 | return | ||
256 | } | ||
257 | if len(subpacket) != 4 { | ||
258 | err = errors.StructuralError("signature creation time not four bytes") | ||
259 | return | ||
260 | } | ||
261 | t := binary.BigEndian.Uint32(subpacket) | ||
262 | sig.CreationTime = time.Unix(int64(t), 0) | ||
263 | case signatureExpirationSubpacket: | ||
264 | // Signature expiration time, section 5.2.3.10 | ||
265 | if !isHashed { | ||
266 | return | ||
267 | } | ||
268 | if len(subpacket) != 4 { | ||
269 | err = errors.StructuralError("expiration subpacket with bad length") | ||
270 | return | ||
271 | } | ||
272 | sig.SigLifetimeSecs = new(uint32) | ||
273 | *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) | ||
274 | case keyExpirationSubpacket: | ||
275 | // Key expiration time, section 5.2.3.6 | ||
276 | if !isHashed { | ||
277 | return | ||
278 | } | ||
279 | if len(subpacket) != 4 { | ||
280 | err = errors.StructuralError("key expiration subpacket with bad length") | ||
281 | return | ||
282 | } | ||
283 | sig.KeyLifetimeSecs = new(uint32) | ||
284 | *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket) | ||
285 | case prefSymmetricAlgosSubpacket: | ||
286 | // Preferred symmetric algorithms, section 5.2.3.7 | ||
287 | if !isHashed { | ||
288 | return | ||
289 | } | ||
290 | sig.PreferredSymmetric = make([]byte, len(subpacket)) | ||
291 | copy(sig.PreferredSymmetric, subpacket) | ||
292 | case issuerSubpacket: | ||
293 | // Issuer, section 5.2.3.5 | ||
294 | if len(subpacket) != 8 { | ||
295 | err = errors.StructuralError("issuer subpacket with bad length") | ||
296 | return | ||
297 | } | ||
298 | sig.IssuerKeyId = new(uint64) | ||
299 | *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket) | ||
300 | case prefHashAlgosSubpacket: | ||
301 | // Preferred hash algorithms, section 5.2.3.8 | ||
302 | if !isHashed { | ||
303 | return | ||
304 | } | ||
305 | sig.PreferredHash = make([]byte, len(subpacket)) | ||
306 | copy(sig.PreferredHash, subpacket) | ||
307 | case prefCompressionSubpacket: | ||
308 | // Preferred compression algorithms, section 5.2.3.9 | ||
309 | if !isHashed { | ||
310 | return | ||
311 | } | ||
312 | sig.PreferredCompression = make([]byte, len(subpacket)) | ||
313 | copy(sig.PreferredCompression, subpacket) | ||
314 | case primaryUserIdSubpacket: | ||
315 | // Primary User ID, section 5.2.3.19 | ||
316 | if !isHashed { | ||
317 | return | ||
318 | } | ||
319 | if len(subpacket) != 1 { | ||
320 | err = errors.StructuralError("primary user id subpacket with bad length") | ||
321 | return | ||
322 | } | ||
323 | sig.IsPrimaryId = new(bool) | ||
324 | if subpacket[0] > 0 { | ||
325 | *sig.IsPrimaryId = true | ||
326 | } | ||
327 | case keyFlagsSubpacket: | ||
328 | // Key flags, section 5.2.3.21 | ||
329 | if !isHashed { | ||
330 | return | ||
331 | } | ||
332 | if len(subpacket) == 0 { | ||
333 | err = errors.StructuralError("empty key flags subpacket") | ||
334 | return | ||
335 | } | ||
336 | sig.FlagsValid = true | ||
337 | if subpacket[0]&KeyFlagCertify != 0 { | ||
338 | sig.FlagCertify = true | ||
339 | } | ||
340 | if subpacket[0]&KeyFlagSign != 0 { | ||
341 | sig.FlagSign = true | ||
342 | } | ||
343 | if subpacket[0]&KeyFlagEncryptCommunications != 0 { | ||
344 | sig.FlagEncryptCommunications = true | ||
345 | } | ||
346 | if subpacket[0]&KeyFlagEncryptStorage != 0 { | ||
347 | sig.FlagEncryptStorage = true | ||
348 | } | ||
349 | case reasonForRevocationSubpacket: | ||
350 | // Reason For Revocation, section 5.2.3.23 | ||
351 | if !isHashed { | ||
352 | return | ||
353 | } | ||
354 | if len(subpacket) == 0 { | ||
355 | err = errors.StructuralError("empty revocation reason subpacket") | ||
356 | return | ||
357 | } | ||
358 | sig.RevocationReason = new(uint8) | ||
359 | *sig.RevocationReason = subpacket[0] | ||
360 | sig.RevocationReasonText = string(subpacket[1:]) | ||
361 | case featuresSubpacket: | ||
362 | // Features subpacket, section 5.2.3.24 specifies a very general | ||
363 | // mechanism for OpenPGP implementations to signal support for new | ||
364 | // features. In practice, the subpacket is used exclusively to | ||
365 | // indicate support for MDC-protected encryption. | ||
366 | sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1 | ||
367 | case embeddedSignatureSubpacket: | ||
368 | // Only usage is in signatures that cross-certify | ||
369 | // signing subkeys. section 5.2.3.26 describes the | ||
370 | // format, with its usage described in section 11.1 | ||
371 | if sig.EmbeddedSignature != nil { | ||
372 | err = errors.StructuralError("Cannot have multiple embedded signatures") | ||
373 | return | ||
374 | } | ||
375 | sig.EmbeddedSignature = new(Signature) | ||
376 | // Embedded signatures are required to be v4 signatures see | ||
377 | // section 12.1. However, we only parse v4 signatures in this | ||
378 | // file anyway. | ||
379 | if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil { | ||
380 | return nil, err | ||
381 | } | ||
382 | if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding { | ||
383 | return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType))) | ||
384 | } | ||
385 | default: | ||
386 | if isCritical { | ||
387 | err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) | ||
388 | return | ||
389 | } | ||
390 | } | ||
391 | return | ||
392 | |||
393 | Truncated: | ||
394 | err = errors.StructuralError("signature subpacket truncated") | ||
395 | return | ||
396 | } | ||
397 | |||
398 | // subpacketLengthLength returns the length, in bytes, of an encoded length value. | ||
399 | func subpacketLengthLength(length int) int { | ||
400 | if length < 192 { | ||
401 | return 1 | ||
402 | } | ||
403 | if length < 16320 { | ||
404 | return 2 | ||
405 | } | ||
406 | return 5 | ||
407 | } | ||
408 | |||
409 | // serializeSubpacketLength marshals the given length into to. | ||
410 | func serializeSubpacketLength(to []byte, length int) int { | ||
411 | // RFC 4880, Section 4.2.2. | ||
412 | if length < 192 { | ||
413 | to[0] = byte(length) | ||
414 | return 1 | ||
415 | } | ||
416 | if length < 16320 { | ||
417 | length -= 192 | ||
418 | to[0] = byte((length >> 8) + 192) | ||
419 | to[1] = byte(length) | ||
420 | return 2 | ||
421 | } | ||
422 | to[0] = 255 | ||
423 | to[1] = byte(length >> 24) | ||
424 | to[2] = byte(length >> 16) | ||
425 | to[3] = byte(length >> 8) | ||
426 | to[4] = byte(length) | ||
427 | return 5 | ||
428 | } | ||
429 | |||
430 | // subpacketsLength returns the serialized length, in bytes, of the given | ||
431 | // subpackets. | ||
432 | func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) { | ||
433 | for _, subpacket := range subpackets { | ||
434 | if subpacket.hashed == hashed { | ||
435 | length += subpacketLengthLength(len(subpacket.contents) + 1) | ||
436 | length += 1 // type byte | ||
437 | length += len(subpacket.contents) | ||
438 | } | ||
439 | } | ||
440 | return | ||
441 | } | ||
442 | |||
443 | // serializeSubpackets marshals the given subpackets into to. | ||
444 | func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { | ||
445 | for _, subpacket := range subpackets { | ||
446 | if subpacket.hashed == hashed { | ||
447 | n := serializeSubpacketLength(to, len(subpacket.contents)+1) | ||
448 | to[n] = byte(subpacket.subpacketType) | ||
449 | to = to[1+n:] | ||
450 | n = copy(to, subpacket.contents) | ||
451 | to = to[n:] | ||
452 | } | ||
453 | } | ||
454 | return | ||
455 | } | ||
456 | |||
457 | // KeyExpired returns whether sig is a self-signature of a key that has | ||
458 | // expired. | ||
459 | func (sig *Signature) KeyExpired(currentTime time.Time) bool { | ||
460 | if sig.KeyLifetimeSecs == nil { | ||
461 | return false | ||
462 | } | ||
463 | expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) | ||
464 | return currentTime.After(expiry) | ||
465 | } | ||
466 | |||
467 | // buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. | ||
468 | func (sig *Signature) buildHashSuffix() (err error) { | ||
469 | hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) | ||
470 | |||
471 | var ok bool | ||
472 | l := 6 + hashedSubpacketsLen | ||
473 | sig.HashSuffix = make([]byte, l+6) | ||
474 | sig.HashSuffix[0] = 4 | ||
475 | sig.HashSuffix[1] = uint8(sig.SigType) | ||
476 | sig.HashSuffix[2] = uint8(sig.PubKeyAlgo) | ||
477 | sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) | ||
478 | if !ok { | ||
479 | sig.HashSuffix = nil | ||
480 | return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) | ||
481 | } | ||
482 | sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) | ||
483 | sig.HashSuffix[5] = byte(hashedSubpacketsLen) | ||
484 | serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true) | ||
485 | trailer := sig.HashSuffix[l:] | ||
486 | trailer[0] = 4 | ||
487 | trailer[1] = 0xff | ||
488 | trailer[2] = byte(l >> 24) | ||
489 | trailer[3] = byte(l >> 16) | ||
490 | trailer[4] = byte(l >> 8) | ||
491 | trailer[5] = byte(l) | ||
492 | return | ||
493 | } | ||
494 | |||
495 | func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { | ||
496 | err = sig.buildHashSuffix() | ||
497 | if err != nil { | ||
498 | return | ||
499 | } | ||
500 | |||
501 | h.Write(sig.HashSuffix) | ||
502 | digest = h.Sum(nil) | ||
503 | copy(sig.HashTag[:], digest) | ||
504 | return | ||
505 | } | ||
506 | |||
507 | // Sign signs a message with a private key. The hash, h, must contain | ||
508 | // the hash of the message to be signed and will be mutated by this function. | ||
509 | // On success, the signature is stored in sig. Call Serialize to write it out. | ||
510 | // If config is nil, sensible defaults will be used. | ||
511 | func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { | ||
512 | sig.outSubpackets = sig.buildSubpackets() | ||
513 | digest, err := sig.signPrepareHash(h) | ||
514 | if err != nil { | ||
515 | return | ||
516 | } | ||
517 | |||
518 | switch priv.PubKeyAlgo { | ||
519 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: | ||
520 | // supports both *rsa.PrivateKey and crypto.Signer | ||
521 | sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) | ||
522 | sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) | ||
523 | case PubKeyAlgoDSA: | ||
524 | dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) | ||
525 | |||
526 | // Need to truncate hashBytes to match FIPS 186-3 section 4.6. | ||
527 | subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 | ||
528 | if len(digest) > subgroupSize { | ||
529 | digest = digest[:subgroupSize] | ||
530 | } | ||
531 | r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) | ||
532 | if err == nil { | ||
533 | sig.DSASigR.bytes = r.Bytes() | ||
534 | sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) | ||
535 | sig.DSASigS.bytes = s.Bytes() | ||
536 | sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) | ||
537 | } | ||
538 | case PubKeyAlgoECDSA: | ||
539 | var r, s *big.Int | ||
540 | if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok { | ||
541 | // direct support, avoid asn1 wrapping/unwrapping | ||
542 | r, s, err = ecdsa.Sign(config.Random(), pk, digest) | ||
543 | } else { | ||
544 | var b []byte | ||
545 | b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, nil) | ||
546 | if err == nil { | ||
547 | r, s, err = unwrapECDSASig(b) | ||
548 | } | ||
549 | } | ||
550 | if err == nil { | ||
551 | sig.ECDSASigR = fromBig(r) | ||
552 | sig.ECDSASigS = fromBig(s) | ||
553 | } | ||
554 | default: | ||
555 | err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) | ||
556 | } | ||
557 | |||
558 | return | ||
559 | } | ||
560 | |||
561 | // unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA | ||
562 | // signature. | ||
563 | func unwrapECDSASig(b []byte) (r, s *big.Int, err error) { | ||
564 | var ecsdaSig struct { | ||
565 | R, S *big.Int | ||
566 | } | ||
567 | _, err = asn1.Unmarshal(b, &ecsdaSig) | ||
568 | if err != nil { | ||
569 | return | ||
570 | } | ||
571 | return ecsdaSig.R, ecsdaSig.S, nil | ||
572 | } | ||
573 | |||
574 | // SignUserId computes a signature from priv, asserting that pub is a valid | ||
575 | // key for the identity id. On success, the signature is stored in sig. Call | ||
576 | // Serialize to write it out. | ||
577 | // If config is nil, sensible defaults will be used. | ||
578 | func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { | ||
579 | h, err := userIdSignatureHash(id, pub, sig.Hash) | ||
580 | if err != nil { | ||
581 | return err | ||
582 | } | ||
583 | return sig.Sign(h, priv, config) | ||
584 | } | ||
585 | |||
586 | // SignKey computes a signature from priv, asserting that pub is a subkey. On | ||
587 | // success, the signature is stored in sig. Call Serialize to write it out. | ||
588 | // If config is nil, sensible defaults will be used. | ||
589 | func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { | ||
590 | h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash) | ||
591 | if err != nil { | ||
592 | return err | ||
593 | } | ||
594 | return sig.Sign(h, priv, config) | ||
595 | } | ||
596 | |||
597 | // Serialize marshals sig to w. Sign, SignUserId or SignKey must have been | ||
598 | // called first. | ||
599 | func (sig *Signature) Serialize(w io.Writer) (err error) { | ||
600 | if len(sig.outSubpackets) == 0 { | ||
601 | sig.outSubpackets = sig.rawSubpackets | ||
602 | } | ||
603 | if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil { | ||
604 | return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") | ||
605 | } | ||
606 | |||
607 | sigLength := 0 | ||
608 | switch sig.PubKeyAlgo { | ||
609 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: | ||
610 | sigLength = 2 + len(sig.RSASignature.bytes) | ||
611 | case PubKeyAlgoDSA: | ||
612 | sigLength = 2 + len(sig.DSASigR.bytes) | ||
613 | sigLength += 2 + len(sig.DSASigS.bytes) | ||
614 | case PubKeyAlgoECDSA: | ||
615 | sigLength = 2 + len(sig.ECDSASigR.bytes) | ||
616 | sigLength += 2 + len(sig.ECDSASigS.bytes) | ||
617 | default: | ||
618 | panic("impossible") | ||
619 | } | ||
620 | |||
621 | unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) | ||
622 | length := len(sig.HashSuffix) - 6 /* trailer not included */ + | ||
623 | 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + | ||
624 | 2 /* hash tag */ + sigLength | ||
625 | err = serializeHeader(w, packetTypeSignature, length) | ||
626 | if err != nil { | ||
627 | return | ||
628 | } | ||
629 | |||
630 | _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6]) | ||
631 | if err != nil { | ||
632 | return | ||
633 | } | ||
634 | |||
635 | unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen) | ||
636 | unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) | ||
637 | unhashedSubpackets[1] = byte(unhashedSubpacketsLen) | ||
638 | serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) | ||
639 | |||
640 | _, err = w.Write(unhashedSubpackets) | ||
641 | if err != nil { | ||
642 | return | ||
643 | } | ||
644 | _, err = w.Write(sig.HashTag[:]) | ||
645 | if err != nil { | ||
646 | return | ||
647 | } | ||
648 | |||
649 | switch sig.PubKeyAlgo { | ||
650 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: | ||
651 | err = writeMPIs(w, sig.RSASignature) | ||
652 | case PubKeyAlgoDSA: | ||
653 | err = writeMPIs(w, sig.DSASigR, sig.DSASigS) | ||
654 | case PubKeyAlgoECDSA: | ||
655 | err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS) | ||
656 | default: | ||
657 | panic("impossible") | ||
658 | } | ||
659 | return | ||
660 | } | ||
661 | |||
662 | // outputSubpacket represents a subpacket to be marshaled. | ||
663 | type outputSubpacket struct { | ||
664 | hashed bool // true if this subpacket is in the hashed area. | ||
665 | subpacketType signatureSubpacketType | ||
666 | isCritical bool | ||
667 | contents []byte | ||
668 | } | ||
669 | |||
670 | func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { | ||
671 | creationTime := make([]byte, 4) | ||
672 | binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) | ||
673 | subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) | ||
674 | |||
675 | if sig.IssuerKeyId != nil { | ||
676 | keyId := make([]byte, 8) | ||
677 | binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) | ||
678 | subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) | ||
679 | } | ||
680 | |||
681 | if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { | ||
682 | sigLifetime := make([]byte, 4) | ||
683 | binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) | ||
684 | subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) | ||
685 | } | ||
686 | |||
687 | // Key flags may only appear in self-signatures or certification signatures. | ||
688 | |||
689 | if sig.FlagsValid { | ||
690 | var flags byte | ||
691 | if sig.FlagCertify { | ||
692 | flags |= KeyFlagCertify | ||
693 | } | ||
694 | if sig.FlagSign { | ||
695 | flags |= KeyFlagSign | ||
696 | } | ||
697 | if sig.FlagEncryptCommunications { | ||
698 | flags |= KeyFlagEncryptCommunications | ||
699 | } | ||
700 | if sig.FlagEncryptStorage { | ||
701 | flags |= KeyFlagEncryptStorage | ||
702 | } | ||
703 | subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) | ||
704 | } | ||
705 | |||
706 | // The following subpackets may only appear in self-signatures | ||
707 | |||
708 | if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { | ||
709 | keyLifetime := make([]byte, 4) | ||
710 | binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) | ||
711 | subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) | ||
712 | } | ||
713 | |||
714 | if sig.IsPrimaryId != nil && *sig.IsPrimaryId { | ||
715 | subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) | ||
716 | } | ||
717 | |||
718 | if len(sig.PreferredSymmetric) > 0 { | ||
719 | subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) | ||
720 | } | ||
721 | |||
722 | if len(sig.PreferredHash) > 0 { | ||
723 | subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) | ||
724 | } | ||
725 | |||
726 | if len(sig.PreferredCompression) > 0 { | ||
727 | subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) | ||
728 | } | ||
729 | |||
730 | return | ||
731 | } | ||