Exemple #1
0
func readHeader(r io.Reader) (tag uint8, length uint64, err os.Error) {
	var buf [4]byte
	_, err = io.ReadFull(r, buf[0:1])
	if err != nil {
		return
	}
	if buf[0]&0x80 == 0 {
		err = error.StructuralError("tag byte does not have MSB set")
		return
	}
	if buf[0]&0x40 == 0 {
		// Old format packet
		tag = (buf[0] & 0x3f) >> 2
		lengthType := buf[0] & 3
		if lengthType == 3 {
			err = error.Unsupported("indeterminate length packet")
			return
		}
		lengthBytes := 1 << lengthType
		_, err = io.ReadFull(r, buf[0:lengthBytes])
		if err != nil {
			return
		}
		for i := 0; i < lengthBytes; i++ {
			length <<= 8
			length |= uint64(buf[i])
		}
		return
	}

	// New format packet
	tag = buf[0] & 0x3f
	_, err = io.ReadFull(r, buf[0:1])
	if err != nil {
		return
	}
	switch {
	case buf[0] < 192:
		length = uint64(buf[0])
	case buf[0] < 224:
		length = uint64(buf[0]-192) << 8
		_, err = io.ReadFull(r, buf[0:1])
		if err != nil {
			return
		}
		length += uint64(buf[0]) + 192
	case buf[0] < 255:
		err = error.Unsupported("chunked packet")
	default:
		_, err := io.ReadFull(r, buf[0:4])
		if err != nil {
			return
		}
		length = uint64(buf[0])<<24 |
			uint64(buf[1])<<16 |
			uint64(buf[2])<<8 |
			uint64(buf[3])
	}
	return
}
Exemple #2
0
func readPublicKeyPacket(r io.Reader, length uint16) (pk PublicKeyPacket, err os.Error) {
	// RFC 4880, section 5.5.2
	var buf [6]byte
	_, err = io.ReadFull(r, buf[0:])
	if err != nil {
		return
	}
	if buf[0] != 4 {
		err = error.Unsupported("public key version")
	}

	// RFC 4880, section 12.2
	fprint := sha1.New()
	fprint.Write([]byte{'\x99', uint8(length >> 8), uint8(length)})
	fprint.Write(buf[0:6]) // version, timestamp, algorithm

	pk.CreationTime = uint32(buf[1])<<24 |
		uint32(buf[2])<<16 |
		uint32(buf[3])<<8 |
		uint32(buf[4])
	pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
	switch pk.PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
		// good.
	case PubKeyAlgoDSA:
		err = error.Unsupported("DSA public key type")
		return
	default:
		err = error.Unsupported(fmt.Sprintf("public key type (%d)", pk.PubKeyAlgo))
		return
	}

	nBytes, mpiHdr, err := readMPI(r)
	if err != nil {
		return
	}
	fprint.Write(mpiHdr[:])
	fprint.Write(nBytes)

	eBytes, mpiHdr, err := readMPI(r)
	if err != nil {
		return
	}
	fprint.Write(mpiHdr[:])
	fprint.Write(eBytes)

	if len(eBytes) > 3 {
		err = error.Unsupported("large public exponent")
		return
	}
	pk.PublicKey.E = 0
	for i := 0; i < len(eBytes); i++ {
		pk.PublicKey.E <<= 8
		pk.PublicKey.E |= int(eBytes[i])
	}
	pk.PublicKey.N = (new(big.Int)).SetBytes(nBytes)
	pk.Fingerprint = fprint.Sum()
	return
}
Exemple #3
0
func ReadPacket(r io.Reader) (p Packet, err os.Error) {
	tag, length, err := readHeader(r)
	limitReader := io.LimitReader(r, int64(length))
	switch tag {
	case 2:
		p, err = readSignaturePacket(limitReader)
	case 6:
		p, err = readPublicKeyPacket(limitReader, uint16(length))
	default:
		err = error.Unsupported("unknown packet type")
	}
	return
}
Exemple #4
0
func parseSignatureSubpacket(sig *SignaturePacket, subpacket []byte, isHashed bool) (rest []byte, err os.Error) {
	// RFC 4880, section 5.2.3.1
	var length uint32
	switch {
	case subpacket[0] < 192:
		length = uint32(subpacket[0])
		subpacket = subpacket[1:]
	case subpacket[0] < 255:
		if len(subpacket) < 2 {
			goto Truncated
		}
		length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
		subpacket = subpacket[2:]
	default:
		if len(subpacket) < 5 {
			goto Truncated
		}
		length = uint32(subpacket[1])<<24 |
			uint32(subpacket[2])<<16 |
			uint32(subpacket[3])<<8 |
			uint32(subpacket[4])
		subpacket = subpacket[5:]
	}
	if length < uint32(len(subpacket)) {
		goto Truncated
	}
	rest = subpacket[length:]
	subpacket = subpacket[:length]
	if len(subpacket) == 0 {
		err = error.StructuralError("zero length signature subpacket")
		return
	}
	packetType := subpacket[0] & 0x7f
	isCritial := subpacket[0]&0x80 == 0x80
	subpacket = subpacket[1:]
	switch packetType {
	case 2:
		if !isHashed {
			err = error.StructuralError("signature creation time in non-hashed area")
			return
		}
		if len(subpacket) != 4 {
			err = error.StructuralError("signature creation time not four bytes")
			return
		}
		sig.CreationTime = uint32(subpacket[0])<<24 |
			uint32(subpacket[1])<<16 |
			uint32(subpacket[2])<<8 |
			uint32(subpacket[3])
	default:
		if isCritial {
			err = error.Unsupported("unknown critical signature subpacket")
			return
		}
	}
	return

Truncated:
	err = error.StructuralError("signature subpacket truncated")
	return
}
Exemple #5
0
func readSignaturePacket(r io.Reader) (sig SignaturePacket, err os.Error) {
	// RFC 4880, section 5.2.3
	var buf [5]byte
	_, err = io.ReadFull(r, buf[:1])
	if err != nil {
		return
	}
	if buf[0] != 4 {
		err = error.Unsupported("signature packet version")
		return
	}

	_, err = io.ReadFull(r, buf[:5])
	if err != nil {
		return
	}
	sig.SigType = SignatureType(buf[0])
	sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
	switch sig.PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
	default:
		err = error.Unsupported("public key algorithm")
		return
	}
	sig.Hash = HashFunction(buf[2])
	hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
	l := 6 + hashedSubpacketsLength
	sig.HashSuffix = make([]byte, l+6)
	sig.HashSuffix[0] = 4
	copy(sig.HashSuffix[1:], buf[:5])
	hashedSubpackets := sig.HashSuffix[6:l]
	_, err = io.ReadFull(r, hashedSubpackets)
	if err != nil {
		return
	}
	// See RFC 4880, section 5.2.4
	trailer := sig.HashSuffix[l:]
	trailer[0] = 4
	trailer[1] = 0xff
	trailer[2] = uint8(l >> 24)
	trailer[3] = uint8(l >> 16)
	trailer[4] = uint8(l >> 8)
	trailer[5] = uint8(l)

	err = parseSignatureSubpackets(&sig, hashedSubpackets, true)
	if err != nil {
		return
	}

	_, err = io.ReadFull(r, buf[:2])
	if err != nil {
		return
	}
	unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
	unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
	_, err = io.ReadFull(r, unhashedSubpackets)
	if err != nil {
		return
	}
	err = parseSignatureSubpackets(&sig, unhashedSubpackets, false)
	if err != nil {
		return
	}

	_, err = io.ReadFull(r, sig.HashTag[:2])
	if err != nil {
		return
	}

	// We have already checked that the public key algorithm is RSA.
	sig.Signature, _, err = readMPI(r)
	return
}