github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/third_party/code.google.com/p/go.crypto/openpgp/packet/signature.go (about) 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 "camlistore.org/third_party/code.google.com/p/go.crypto/openpgp/errors" 9 "camlistore.org/third_party/code.google.com/p/go.crypto/openpgp/s2k" 10 "crypto" 11 "crypto/dsa" 12 "crypto/rsa" 13 "encoding/binary" 14 "hash" 15 "io" 16 "strconv" 17 "time" 18 ) 19 20 // Signature represents a signature. See RFC 4880, section 5.2. 21 type Signature struct { 22 SigType SignatureType 23 PubKeyAlgo PublicKeyAlgorithm 24 Hash crypto.Hash 25 26 // HashSuffix is extra data that is hashed in after the signed data. 27 HashSuffix []byte 28 // HashTag contains the first two bytes of the hash for fast rejection 29 // of bad signed data. 30 HashTag [2]byte 31 CreationTime time.Time 32 33 RSASignature parsedMPI 34 DSASigR, DSASigS parsedMPI 35 36 // rawSubpackets contains the unparsed subpackets, in order. 37 rawSubpackets []outputSubpacket 38 39 // The following are optional so are nil when not included in the 40 // signature. 41 42 SigLifetimeSecs, KeyLifetimeSecs *uint32 43 PreferredSymmetric, PreferredHash, PreferredCompression []uint8 44 IssuerKeyId *uint64 45 IsPrimaryId *bool 46 47 // FlagsValid is set if any flags were given. See RFC 4880, section 48 // 5.2.3.21 for details. 49 FlagsValid bool 50 FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool 51 52 outSubpackets []outputSubpacket 53 } 54 55 func (sig *Signature) parse(r io.Reader) (err error) { 56 // RFC 4880, section 5.2.3 57 var buf [5]byte 58 _, err = readFull(r, buf[:1]) 59 if err != nil { 60 return 61 } 62 if buf[0] != 4 { 63 err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) 64 return 65 } 66 67 _, err = readFull(r, buf[:5]) 68 if err != nil { 69 return 70 } 71 sig.SigType = SignatureType(buf[0]) 72 sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) 73 switch sig.PubKeyAlgo { 74 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: 75 default: 76 err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) 77 return 78 } 79 80 var ok bool 81 sig.Hash, ok = s2k.HashIdToHash(buf[2]) 82 if !ok { 83 return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) 84 } 85 86 hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) 87 l := 6 + hashedSubpacketsLength 88 sig.HashSuffix = make([]byte, l+6) 89 sig.HashSuffix[0] = 4 90 copy(sig.HashSuffix[1:], buf[:5]) 91 hashedSubpackets := sig.HashSuffix[6:l] 92 _, err = readFull(r, hashedSubpackets) 93 if err != nil { 94 return 95 } 96 // See RFC 4880, section 5.2.4 97 trailer := sig.HashSuffix[l:] 98 trailer[0] = 4 99 trailer[1] = 0xff 100 trailer[2] = uint8(l >> 24) 101 trailer[3] = uint8(l >> 16) 102 trailer[4] = uint8(l >> 8) 103 trailer[5] = uint8(l) 104 105 err = parseSignatureSubpackets(sig, hashedSubpackets, true) 106 if err != nil { 107 return 108 } 109 110 _, err = readFull(r, buf[:2]) 111 if err != nil { 112 return 113 } 114 unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1]) 115 unhashedSubpackets := make([]byte, unhashedSubpacketsLength) 116 _, err = readFull(r, unhashedSubpackets) 117 if err != nil { 118 return 119 } 120 err = parseSignatureSubpackets(sig, unhashedSubpackets, false) 121 if err != nil { 122 return 123 } 124 125 _, err = readFull(r, sig.HashTag[:2]) 126 if err != nil { 127 return 128 } 129 130 switch sig.PubKeyAlgo { 131 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: 132 sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) 133 case PubKeyAlgoDSA: 134 sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) 135 if err == nil { 136 sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) 137 } 138 default: 139 panic("unreachable") 140 } 141 return 142 } 143 144 // parseSignatureSubpackets parses subpackets of the main signature packet. See 145 // RFC 4880, section 5.2.3.1. 146 func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) { 147 for len(subpackets) > 0 { 148 subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) 149 if err != nil { 150 return 151 } 152 } 153 154 if sig.CreationTime.IsZero() { 155 err = errors.StructuralError("no creation time in signature") 156 } 157 158 return 159 } 160 161 type signatureSubpacketType uint8 162 163 const ( 164 creationTimeSubpacket signatureSubpacketType = 2 165 signatureExpirationSubpacket signatureSubpacketType = 3 166 keyExpirationSubpacket signatureSubpacketType = 9 167 prefSymmetricAlgosSubpacket signatureSubpacketType = 11 168 issuerSubpacket signatureSubpacketType = 16 169 prefHashAlgosSubpacket signatureSubpacketType = 21 170 prefCompressionSubpacket signatureSubpacketType = 22 171 primaryUserIdSubpacket signatureSubpacketType = 25 172 keyFlagsSubpacket signatureSubpacketType = 27 173 ) 174 175 // parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. 176 func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { 177 // RFC 4880, section 5.2.3.1 178 var ( 179 length uint32 180 packetType signatureSubpacketType 181 isCritical bool 182 ) 183 switch { 184 case subpacket[0] < 192: 185 length = uint32(subpacket[0]) 186 subpacket = subpacket[1:] 187 case subpacket[0] < 255: 188 if len(subpacket) < 2 { 189 goto Truncated 190 } 191 length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192 192 subpacket = subpacket[2:] 193 default: 194 if len(subpacket) < 5 { 195 goto Truncated 196 } 197 length = uint32(subpacket[1])<<24 | 198 uint32(subpacket[2])<<16 | 199 uint32(subpacket[3])<<8 | 200 uint32(subpacket[4]) 201 subpacket = subpacket[5:] 202 } 203 if length > uint32(len(subpacket)) { 204 goto Truncated 205 } 206 rest = subpacket[length:] 207 subpacket = subpacket[:length] 208 if len(subpacket) == 0 { 209 err = errors.StructuralError("zero length signature subpacket") 210 return 211 } 212 packetType = signatureSubpacketType(subpacket[0] & 0x7f) 213 isCritical = subpacket[0]&0x80 == 0x80 214 subpacket = subpacket[1:] 215 sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) 216 switch packetType { 217 case creationTimeSubpacket: 218 if !isHashed { 219 err = errors.StructuralError("signature creation time in non-hashed area") 220 return 221 } 222 if len(subpacket) != 4 { 223 err = errors.StructuralError("signature creation time not four bytes") 224 return 225 } 226 t := binary.BigEndian.Uint32(subpacket) 227 sig.CreationTime = time.Unix(int64(t), 0) 228 case signatureExpirationSubpacket: 229 // Signature expiration time, section 5.2.3.10 230 if !isHashed { 231 return 232 } 233 if len(subpacket) != 4 { 234 err = errors.StructuralError("expiration subpacket with bad length") 235 return 236 } 237 sig.SigLifetimeSecs = new(uint32) 238 *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) 239 case keyExpirationSubpacket: 240 // Key expiration time, section 5.2.3.6 241 if !isHashed { 242 return 243 } 244 if len(subpacket) != 4 { 245 err = errors.StructuralError("key expiration subpacket with bad length") 246 return 247 } 248 sig.KeyLifetimeSecs = new(uint32) 249 *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket) 250 case prefSymmetricAlgosSubpacket: 251 // Preferred symmetric algorithms, section 5.2.3.7 252 if !isHashed { 253 return 254 } 255 sig.PreferredSymmetric = make([]byte, len(subpacket)) 256 copy(sig.PreferredSymmetric, subpacket) 257 case issuerSubpacket: 258 // Issuer, section 5.2.3.5 259 if len(subpacket) != 8 { 260 err = errors.StructuralError("issuer subpacket with bad length") 261 return 262 } 263 sig.IssuerKeyId = new(uint64) 264 *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket) 265 case prefHashAlgosSubpacket: 266 // Preferred hash algorithms, section 5.2.3.8 267 if !isHashed { 268 return 269 } 270 sig.PreferredHash = make([]byte, len(subpacket)) 271 copy(sig.PreferredHash, subpacket) 272 case prefCompressionSubpacket: 273 // Preferred compression algorithms, section 5.2.3.9 274 if !isHashed { 275 return 276 } 277 sig.PreferredCompression = make([]byte, len(subpacket)) 278 copy(sig.PreferredCompression, subpacket) 279 case primaryUserIdSubpacket: 280 // Primary User ID, section 5.2.3.19 281 if !isHashed { 282 return 283 } 284 if len(subpacket) != 1 { 285 err = errors.StructuralError("primary user id subpacket with bad length") 286 return 287 } 288 sig.IsPrimaryId = new(bool) 289 if subpacket[0] > 0 { 290 *sig.IsPrimaryId = true 291 } 292 case keyFlagsSubpacket: 293 // Key flags, section 5.2.3.21 294 if !isHashed { 295 return 296 } 297 if len(subpacket) == 0 { 298 err = errors.StructuralError("empty key flags subpacket") 299 return 300 } 301 sig.FlagsValid = true 302 if subpacket[0]&1 != 0 { 303 sig.FlagCertify = true 304 } 305 if subpacket[0]&2 != 0 { 306 sig.FlagSign = true 307 } 308 if subpacket[0]&4 != 0 { 309 sig.FlagEncryptCommunications = true 310 } 311 if subpacket[0]&8 != 0 { 312 sig.FlagEncryptStorage = true 313 } 314 315 default: 316 if isCritical { 317 err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) 318 return 319 } 320 } 321 return 322 323 Truncated: 324 err = errors.StructuralError("signature subpacket truncated") 325 return 326 } 327 328 // subpacketLengthLength returns the length, in bytes, of an encoded length value. 329 func subpacketLengthLength(length int) int { 330 if length < 192 { 331 return 1 332 } 333 if length < 16320 { 334 return 2 335 } 336 return 5 337 } 338 339 // serializeSubpacketLength marshals the given length into to. 340 func serializeSubpacketLength(to []byte, length int) int { 341 if length < 192 { 342 to[0] = byte(length) 343 return 1 344 } 345 if length < 16320 { 346 length -= 192 347 to[0] = byte(length >> 8) 348 to[1] = byte(length) 349 return 2 350 } 351 to[0] = 255 352 to[1] = byte(length >> 24) 353 to[2] = byte(length >> 16) 354 to[3] = byte(length >> 8) 355 to[4] = byte(length) 356 return 5 357 } 358 359 // subpacketsLength returns the serialized length, in bytes, of the given 360 // subpackets. 361 func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) { 362 for _, subpacket := range subpackets { 363 if subpacket.hashed == hashed { 364 length += subpacketLengthLength(len(subpacket.contents) + 1) 365 length += 1 // type byte 366 length += len(subpacket.contents) 367 } 368 } 369 return 370 } 371 372 // serializeSubpackets marshals the given subpackets into to. 373 func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { 374 for _, subpacket := range subpackets { 375 if subpacket.hashed == hashed { 376 n := serializeSubpacketLength(to, len(subpacket.contents)+1) 377 to[n] = byte(subpacket.subpacketType) 378 to = to[1+n:] 379 n = copy(to, subpacket.contents) 380 to = to[n:] 381 } 382 } 383 return 384 } 385 386 // buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. 387 func (sig *Signature) buildHashSuffix() (err error) { 388 hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) 389 390 var ok bool 391 l := 6 + hashedSubpacketsLen 392 sig.HashSuffix = make([]byte, l+6) 393 sig.HashSuffix[0] = 4 394 sig.HashSuffix[1] = uint8(sig.SigType) 395 sig.HashSuffix[2] = uint8(sig.PubKeyAlgo) 396 sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) 397 if !ok { 398 sig.HashSuffix = nil 399 return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) 400 } 401 sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) 402 sig.HashSuffix[5] = byte(hashedSubpacketsLen) 403 serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true) 404 trailer := sig.HashSuffix[l:] 405 trailer[0] = 4 406 trailer[1] = 0xff 407 trailer[2] = byte(l >> 24) 408 trailer[3] = byte(l >> 16) 409 trailer[4] = byte(l >> 8) 410 trailer[5] = byte(l) 411 return 412 } 413 414 func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { 415 err = sig.buildHashSuffix() 416 if err != nil { 417 return 418 } 419 420 h.Write(sig.HashSuffix) 421 digest = h.Sum(nil) 422 copy(sig.HashTag[:], digest) 423 return 424 } 425 426 // Sign signs a message with a private key. The hash, h, must contain 427 // the hash of the message to be signed and will be mutated by this function. 428 // On success, the signature is stored in sig. Call Serialize to write it out. 429 func (sig *Signature) Sign(rand io.Reader, h hash.Hash, priv *PrivateKey) (err error) { 430 sig.outSubpackets = sig.buildSubpackets() 431 digest, err := sig.signPrepareHash(h) 432 if err != nil { 433 return 434 } 435 436 switch priv.PubKeyAlgo { 437 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: 438 sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest) 439 sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) 440 case PubKeyAlgoDSA: 441 dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) 442 443 // Need to truncate hashBytes to match FIPS 186-3 section 4.6. 444 subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 445 if len(digest) > subgroupSize { 446 digest = digest[:subgroupSize] 447 } 448 r, s, err := dsa.Sign(rand, dsaPriv, digest) 449 if err == nil { 450 sig.DSASigR.bytes = r.Bytes() 451 sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) 452 sig.DSASigS.bytes = s.Bytes() 453 sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) 454 } 455 default: 456 err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) 457 } 458 459 return 460 } 461 462 // SignUserId computes a signature from priv, asserting that pub is a valid 463 // key for the identity id. On success, the signature is stored in sig. Call 464 // Serialize to write it out. 465 func (sig *Signature) SignUserId(rand io.Reader, id string, pub *PublicKey, priv *PrivateKey) error { 466 h, err := userIdSignatureHash(id, pub, sig) 467 if err != nil { 468 return nil 469 } 470 return sig.Sign(rand, h, priv) 471 } 472 473 // SignKey computes a signature from priv, asserting that pub is a subkey. On 474 // success, the signature is stored in sig. Call Serialize to write it out. 475 func (sig *Signature) SignKey(rand io.Reader, pub *PublicKey, priv *PrivateKey) error { 476 h, err := keySignatureHash(&priv.PublicKey, pub, sig) 477 if err != nil { 478 return err 479 } 480 return sig.Sign(rand, h, priv) 481 } 482 483 // Serialize marshals sig to w. SignRSA or SignDSA must have been called first. 484 func (sig *Signature) Serialize(w io.Writer) (err error) { 485 if len(sig.outSubpackets) == 0 { 486 sig.outSubpackets = sig.rawSubpackets 487 } 488 if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { 489 return errors.InvalidArgumentError("Signature: need to call SignRSA or SignDSA before Serialize") 490 } 491 492 sigLength := 0 493 switch sig.PubKeyAlgo { 494 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: 495 sigLength = 2 + len(sig.RSASignature.bytes) 496 case PubKeyAlgoDSA: 497 sigLength = 2 + len(sig.DSASigR.bytes) 498 sigLength += 2 + len(sig.DSASigS.bytes) 499 default: 500 panic("impossible") 501 } 502 503 unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) 504 length := len(sig.HashSuffix) - 6 /* trailer not included */ + 505 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + 506 2 /* hash tag */ + sigLength 507 err = serializeHeader(w, packetTypeSignature, length) 508 if err != nil { 509 return 510 } 511 512 _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6]) 513 if err != nil { 514 return 515 } 516 517 unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen) 518 unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) 519 unhashedSubpackets[1] = byte(unhashedSubpacketsLen) 520 serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) 521 522 _, err = w.Write(unhashedSubpackets) 523 if err != nil { 524 return 525 } 526 _, err = w.Write(sig.HashTag[:]) 527 if err != nil { 528 return 529 } 530 531 switch sig.PubKeyAlgo { 532 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: 533 err = writeMPIs(w, sig.RSASignature) 534 case PubKeyAlgoDSA: 535 err = writeMPIs(w, sig.DSASigR, sig.DSASigS) 536 default: 537 panic("impossible") 538 } 539 return 540 } 541 542 // outputSubpacket represents a subpacket to be marshaled. 543 type outputSubpacket struct { 544 hashed bool // true if this subpacket is in the hashed area. 545 subpacketType signatureSubpacketType 546 isCritical bool 547 contents []byte 548 } 549 550 func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { 551 creationTime := make([]byte, 4) 552 binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) 553 subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) 554 555 if sig.IssuerKeyId != nil { 556 keyId := make([]byte, 8) 557 binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) 558 subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) 559 } 560 561 if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { 562 sigLifetime := make([]byte, 4) 563 binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) 564 subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) 565 } 566 567 // Key flags may only appear in self-signatures or certification signatures. 568 569 if sig.FlagsValid { 570 var flags byte 571 if sig.FlagCertify { 572 flags |= 1 573 } 574 if sig.FlagSign { 575 flags |= 2 576 } 577 if sig.FlagEncryptCommunications { 578 flags |= 4 579 } 580 if sig.FlagEncryptStorage { 581 flags |= 8 582 } 583 subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) 584 } 585 586 // The following subpackets may only appear in self-signatures 587 588 if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { 589 keyLifetime := make([]byte, 4) 590 binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) 591 subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) 592 } 593 594 if sig.IsPrimaryId != nil && *sig.IsPrimaryId { 595 subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) 596 } 597 598 if len(sig.PreferredSymmetric) > 0 { 599 subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) 600 } 601 602 if len(sig.PreferredHash) > 0 { 603 subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) 604 } 605 606 if len(sig.PreferredCompression) > 0 { 607 subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) 608 } 609 610 return 611 }