1// Copyright 2013 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
5package packet
6
7import (
8	"crypto"
9	"crypto/md5"
10	"crypto/rsa"
11	"encoding/binary"
12	"fmt"
13	"hash"
14	"io"
15	"math/big"
16	"strconv"
17	"time"
18
19	"golang.org/x/crypto/openpgp/errors"
20)
21
22// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and
23// should not be used for signing or encrypting. They are supported here only for
24// parsing version 3 key material and validating signatures.
25// See RFC 4880, section 5.5.2.
26type PublicKeyV3 struct {
27	CreationTime time.Time
28	DaysToExpire uint16
29	PubKeyAlgo   PublicKeyAlgorithm
30	PublicKey    *rsa.PublicKey
31	Fingerprint  [16]byte
32	KeyId        uint64
33	IsSubkey     bool
34
35	n, e parsedMPI
36}
37
38// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey.
39// Included here for testing purposes only. RFC 4880, section 5.5.2:
40// "an implementation MUST NOT generate a V3 key, but MAY accept it."
41func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 {
42	pk := &PublicKeyV3{
43		CreationTime: creationTime,
44		PublicKey:    pub,
45		n:            fromBig(pub.N),
46		e:            fromBig(big.NewInt(int64(pub.E))),
47	}
48
49	pk.setFingerPrintAndKeyId()
50	return pk
51}
52
53func (pk *PublicKeyV3) parse(r io.Reader) (err error) {
54	// RFC 4880, section 5.5.2
55	var buf [8]byte
56	if _, err = readFull(r, buf[:]); err != nil {
57		return
58	}
59	if buf[0] < 2 || buf[0] > 3 {
60		return errors.UnsupportedError("public key version")
61	}
62	pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
63	pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7])
64	pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7])
65	switch pk.PubKeyAlgo {
66	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
67		err = pk.parseRSA(r)
68	default:
69		err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
70	}
71	if err != nil {
72		return
73	}
74
75	pk.setFingerPrintAndKeyId()
76	return
77}
78
79func (pk *PublicKeyV3) setFingerPrintAndKeyId() {
80	// RFC 4880, section 12.2
81	fingerPrint := md5.New()
82	fingerPrint.Write(pk.n.bytes)
83	fingerPrint.Write(pk.e.bytes)
84	fingerPrint.Sum(pk.Fingerprint[:0])
85	pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:])
86}
87
88// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
89// section 5.5.2.
90func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) {
91	if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil {
92		return
93	}
94	if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil {
95		return
96	}
97
98	// RFC 4880 Section 12.2 requires the low 8 bytes of the
99	// modulus to form the key id.
100	if len(pk.n.bytes) < 8 {
101		return errors.StructuralError("v3 public key modulus is too short")
102	}
103	if len(pk.e.bytes) > 3 {
104		err = errors.UnsupportedError("large public exponent")
105		return
106	}
107	rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
108	for i := 0; i < len(pk.e.bytes); i++ {
109		rsa.E <<= 8
110		rsa.E |= int(pk.e.bytes[i])
111	}
112	pk.PublicKey = rsa
113	return
114}
115
116// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
117// The prefix is used when calculating a signature over this public key. See
118// RFC 4880, section 5.2.4.
119func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) {
120	var pLength uint16
121	switch pk.PubKeyAlgo {
122	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
123		pLength += 2 + uint16(len(pk.n.bytes))
124		pLength += 2 + uint16(len(pk.e.bytes))
125	default:
126		panic("unknown public key algorithm")
127	}
128	pLength += 6
129	w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
130	return
131}
132
133func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) {
134	length := 8 // 8 byte header
135
136	switch pk.PubKeyAlgo {
137	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
138		length += 2 + len(pk.n.bytes)
139		length += 2 + len(pk.e.bytes)
140	default:
141		panic("unknown public key algorithm")
142	}
143
144	packetType := packetTypePublicKey
145	if pk.IsSubkey {
146		packetType = packetTypePublicSubkey
147	}
148	if err = serializeHeader(w, packetType, length); err != nil {
149		return
150	}
151	return pk.serializeWithoutHeaders(w)
152}
153
154// serializeWithoutHeaders marshals the PublicKey to w in the form of an
155// OpenPGP public key packet, not including the packet header.
156func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) {
157	var buf [8]byte
158	// Version 3
159	buf[0] = 3
160	// Creation time
161	t := uint32(pk.CreationTime.Unix())
162	buf[1] = byte(t >> 24)
163	buf[2] = byte(t >> 16)
164	buf[3] = byte(t >> 8)
165	buf[4] = byte(t)
166	// Days to expire
167	buf[5] = byte(pk.DaysToExpire >> 8)
168	buf[6] = byte(pk.DaysToExpire)
169	// Public key algorithm
170	buf[7] = byte(pk.PubKeyAlgo)
171
172	if _, err = w.Write(buf[:]); err != nil {
173		return
174	}
175
176	switch pk.PubKeyAlgo {
177	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
178		return writeMPIs(w, pk.n, pk.e)
179	}
180	return errors.InvalidArgumentError("bad public-key algorithm")
181}
182
183// CanSign returns true iff this public key can generate signatures
184func (pk *PublicKeyV3) CanSign() bool {
185	return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly
186}
187
188// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
189// public key, of the data hashed into signed. signed is mutated by this call.
190func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
191	if !pk.CanSign() {
192		return errors.InvalidArgumentError("public key cannot generate signatures")
193	}
194
195	suffix := make([]byte, 5)
196	suffix[0] = byte(sig.SigType)
197	binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
198	signed.Write(suffix)
199	hashBytes := signed.Sum(nil)
200
201	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
202		return errors.SignatureError("hash tag doesn't match")
203	}
204
205	if pk.PubKeyAlgo != sig.PubKeyAlgo {
206		return errors.InvalidArgumentError("public key and signature use different algorithms")
207	}
208
209	switch pk.PubKeyAlgo {
210	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
211		if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
212			return errors.SignatureError("RSA verification failure")
213		}
214		return
215	default:
216		// V3 public keys only support RSA.
217		panic("shouldn't happen")
218	}
219}
220
221// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
222// public key, that id is the identity of pub.
223func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) {
224	h, err := userIdSignatureV3Hash(id, pk, sig.Hash)
225	if err != nil {
226		return err
227	}
228	return pk.VerifySignatureV3(h, sig)
229}
230
231// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this
232// public key, of signed.
233func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) {
234	h, err := keySignatureHash(pk, signed, sig.Hash)
235	if err != nil {
236		return err
237	}
238	return pk.VerifySignatureV3(h, sig)
239}
240
241// userIdSignatureV3Hash returns a Hash of the message that needs to be signed
242// to assert that pk is a valid key for id.
243func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) {
244	if !hfn.Available() {
245		return nil, errors.UnsupportedError("hash function")
246	}
247	h = hfn.New()
248
249	// RFC 4880, section 5.2.4
250	pk.SerializeSignaturePrefix(h)
251	pk.serializeWithoutHeaders(h)
252
253	h.Write([]byte(id))
254
255	return
256}
257
258// KeyIdString returns the public key's fingerprint in capital hex
259// (e.g. "6C7EE1B8621CC013").
260func (pk *PublicKeyV3) KeyIdString() string {
261	return fmt.Sprintf("%X", pk.KeyId)
262}
263
264// KeyIdShortString returns the short form of public key's fingerprint
265// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
266func (pk *PublicKeyV3) KeyIdShortString() string {
267	return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF)
268}
269
270// BitLength returns the bit length for the given public key.
271func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) {
272	switch pk.PubKeyAlgo {
273	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
274		bitLength = pk.n.bitLength
275	default:
276		err = errors.InvalidArgumentError("bad public-key algorithm")
277	}
278	return
279}
280