diff options
Diffstat (limited to 'libgo/go/crypto/openpgp/packet/signature.go')
-rw-r--r-- | libgo/go/crypto/openpgp/packet/signature.go | 117 |
1 files changed, 84 insertions, 33 deletions
diff --git a/libgo/go/crypto/openpgp/packet/signature.go b/libgo/go/crypto/openpgp/packet/signature.go index 1cdc1ee0f0c..c3ffb3a6fb9 100644 --- a/libgo/go/crypto/openpgp/packet/signature.go +++ b/libgo/go/crypto/openpgp/packet/signature.go @@ -7,9 +7,8 @@ package packet import ( "crypto" "crypto/dsa" - error_ "crypto/openpgp/error" + "crypto/openpgp/errors" "crypto/openpgp/s2k" - "crypto/rand" "crypto/rsa" "encoding/binary" "hash" @@ -61,7 +60,7 @@ func (sig *Signature) parse(r io.Reader) (err error) { return } if buf[0] != 4 { - err = error_.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) + err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) return } @@ -74,14 +73,14 @@ func (sig *Signature) parse(r io.Reader) (err error) { switch sig.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: default: - err = error_.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) + err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) return } var ok bool sig.Hash, ok = s2k.HashIdToHash(buf[2]) if !ok { - return error_.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) + return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) } hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) @@ -153,7 +152,7 @@ func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) } if sig.CreationTime.IsZero() { - err = error_.StructuralError("no creation time in signature") + err = errors.StructuralError("no creation time in signature") } return @@ -164,7 +163,7 @@ type signatureSubpacketType uint8 const ( creationTimeSubpacket signatureSubpacketType = 2 signatureExpirationSubpacket signatureSubpacketType = 3 - keyExpirySubpacket signatureSubpacketType = 9 + keyExpirationSubpacket signatureSubpacketType = 9 prefSymmetricAlgosSubpacket signatureSubpacketType = 11 issuerSubpacket signatureSubpacketType = 16 prefHashAlgosSubpacket signatureSubpacketType = 21 @@ -207,7 +206,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r rest = subpacket[length:] subpacket = subpacket[:length] if len(subpacket) == 0 { - err = error_.StructuralError("zero length signature subpacket") + err = errors.StructuralError("zero length signature subpacket") return } packetType = signatureSubpacketType(subpacket[0] & 0x7f) @@ -217,37 +216,33 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r switch packetType { case creationTimeSubpacket: if !isHashed { - err = error_.StructuralError("signature creation time in non-hashed area") + err = errors.StructuralError("signature creation time in non-hashed area") return } if len(subpacket) != 4 { - err = error_.StructuralError("signature creation time not four bytes") + err = errors.StructuralError("signature creation time not four bytes") return } t := binary.BigEndian.Uint32(subpacket) - if t == 0 { - sig.CreationTime = time.Time{} - } else { - sig.CreationTime = time.Unix(int64(t), 0) - } + sig.CreationTime = time.Unix(int64(t), 0) case signatureExpirationSubpacket: // Signature expiration time, section 5.2.3.10 if !isHashed { return } if len(subpacket) != 4 { - err = error_.StructuralError("expiration subpacket with bad length") + err = errors.StructuralError("expiration subpacket with bad length") return } sig.SigLifetimeSecs = new(uint32) *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) - case keyExpirySubpacket: + case keyExpirationSubpacket: // Key expiration time, section 5.2.3.6 if !isHashed { return } if len(subpacket) != 4 { - err = error_.StructuralError("key expiration subpacket with bad length") + err = errors.StructuralError("key expiration subpacket with bad length") return } sig.KeyLifetimeSecs = new(uint32) @@ -262,7 +257,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r case issuerSubpacket: // Issuer, section 5.2.3.5 if len(subpacket) != 8 { - err = error_.StructuralError("issuer subpacket with bad length") + err = errors.StructuralError("issuer subpacket with bad length") return } sig.IssuerKeyId = new(uint64) @@ -287,7 +282,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r return } if len(subpacket) != 1 { - err = error_.StructuralError("primary user id subpacket with bad length") + err = errors.StructuralError("primary user id subpacket with bad length") return } sig.IsPrimaryId = new(bool) @@ -300,7 +295,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r return } if len(subpacket) == 0 { - err = error_.StructuralError("empty key flags subpacket") + err = errors.StructuralError("empty key flags subpacket") return } sig.FlagsValid = true @@ -319,14 +314,14 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r default: if isCritical { - err = error_.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) + err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) return } } return Truncated: - err = error_.StructuralError("signature subpacket truncated") + err = errors.StructuralError("signature subpacket truncated") return } @@ -401,7 +396,7 @@ func (sig *Signature) buildHashSuffix() (err error) { sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) if !ok { sig.HashSuffix = nil - return error_.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) + return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) } sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) sig.HashSuffix[5] = byte(hashedSubpacketsLen) @@ -431,7 +426,7 @@ func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { // Sign signs a message with a private key. The hash, h, must contain // the hash of the message to be signed and will be mutated by this function. // On success, the signature is stored in sig. Call Serialize to write it out. -func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err error) { +func (sig *Signature) Sign(rand io.Reader, h hash.Hash, priv *PrivateKey) (err error) { sig.outSubpackets = sig.buildSubpackets() digest, err := sig.signPrepareHash(h) if err != nil { @@ -440,10 +435,17 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err error) { switch priv.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand.Reader, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest) + sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest) sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) case PubKeyAlgoDSA: - r, s, err := dsa.Sign(rand.Reader, priv.PrivateKey.(*dsa.PrivateKey), digest) + dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) + + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 + if len(digest) > subgroupSize { + digest = digest[:subgroupSize] + } + r, s, err := dsa.Sign(rand, dsaPriv, digest) if err == nil { sig.DSASigR.bytes = r.Bytes() sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) @@ -451,7 +453,7 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err error) { sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) } default: - err = error_.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) + err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) } return @@ -460,22 +462,22 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err error) { // SignUserId computes a signature from priv, asserting that pub is a valid // key for the identity id. On success, the signature is stored in sig. Call // Serialize to write it out. -func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey) error { +func (sig *Signature) SignUserId(rand io.Reader, id string, pub *PublicKey, priv *PrivateKey) error { h, err := userIdSignatureHash(id, pub, sig) if err != nil { return nil } - return sig.Sign(h, priv) + return sig.Sign(rand, h, priv) } // SignKey computes a signature from priv, asserting that pub is a subkey. On // success, the signature is stored in sig. Call Serialize to write it out. -func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey) error { +func (sig *Signature) SignKey(rand io.Reader, pub *PublicKey, priv *PrivateKey) error { h, err := keySignatureHash(&priv.PublicKey, pub, sig) if err != nil { return err } - return sig.Sign(h, priv) + return sig.Sign(rand, h, priv) } // Serialize marshals sig to w. SignRSA or SignDSA must have been called first. @@ -484,7 +486,7 @@ func (sig *Signature) Serialize(w io.Writer) (err error) { sig.outSubpackets = sig.rawSubpackets } if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { - return error_.InvalidArgumentError("Signature: need to call SignRSA or SignDSA before Serialize") + return errors.InvalidArgumentError("Signature: need to call SignRSA or SignDSA before Serialize") } sigLength := 0 @@ -556,5 +558,54 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) } + if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { + sigLifetime := make([]byte, 4) + binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) + subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) + } + + // Key flags may only appear in self-signatures or certification signatures. + + if sig.FlagsValid { + var flags byte + if sig.FlagCertify { + flags |= 1 + } + if sig.FlagSign { + flags |= 2 + } + if sig.FlagEncryptCommunications { + flags |= 4 + } + if sig.FlagEncryptStorage { + flags |= 8 + } + subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) + } + + // The following subpackets may only appear in self-signatures + + if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { + keyLifetime := make([]byte, 4) + binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) + subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) + } + + if sig.IsPrimaryId != nil && *sig.IsPrimaryId { + subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) + } + + if len(sig.PreferredSymmetric) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) + } + + if len(sig.PreferredHash) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) + } + + if len(sig.PreferredCompression) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) + } + return } |