|
| 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 | +// This package implements parsing and serialisation of OpenPGP packets, as |
| 6 | +// specified in RFC 4880. |
| 7 | +package packet |
| 8 | + |
| 9 | +import ( |
| 10 | + "crypto/aes" |
| 11 | + "crypto/cast5" |
| 12 | + "crypto/cipher" |
| 13 | + "crypto/openpgp/error" |
| 14 | + "io" |
| 15 | + "os" |
| 16 | +) |
| 17 | + |
| 18 | +// readFull is the same as io.ReadFull except that reading zero bytes returns |
| 19 | +// ErrUnexpectedEOF rather than EOF. |
| 20 | +func readFull(r io.Reader, buf []byte) (n int, err os.Error) { |
| 21 | + n, err = io.ReadFull(r, buf) |
| 22 | + if err == os.EOF { |
| 23 | + err = io.ErrUnexpectedEOF |
| 24 | + } |
| 25 | + return |
| 26 | +} |
| 27 | + |
| 28 | +// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2. |
| 29 | +func readLength(r io.Reader) (length int64, isPartial bool, err os.Error) { |
| 30 | + var buf [4]byte |
| 31 | + _, err = readFull(r, buf[:1]) |
| 32 | + if err != nil { |
| 33 | + return |
| 34 | + } |
| 35 | + switch { |
| 36 | + case buf[0] < 192: |
| 37 | + length = int64(buf[0]) |
| 38 | + case buf[0] < 224: |
| 39 | + length = int64(buf[0]-192) << 8 |
| 40 | + _, err = readFull(r, buf[0:1]) |
| 41 | + if err != nil { |
| 42 | + return |
| 43 | + } |
| 44 | + length += int64(buf[0]) + 192 |
| 45 | + case buf[0] < 255: |
| 46 | + length = int64(1) << (buf[0] & 0x1f) |
| 47 | + isPartial = true |
| 48 | + default: |
| 49 | + _, err = readFull(r, buf[0:4]) |
| 50 | + if err != nil { |
| 51 | + return |
| 52 | + } |
| 53 | + length = int64(buf[0])<<24 | |
| 54 | + int64(buf[1])<<16 | |
| 55 | + int64(buf[2])<<8 | |
| 56 | + int64(buf[3]) |
| 57 | + } |
| 58 | + return |
| 59 | +} |
| 60 | + |
| 61 | +// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths. |
| 62 | +// The continuation lengths are parsed and removed from the stream and EOF is |
| 63 | +// returned at the end of the packet. See RFC 4880, section 4.2.2.4. |
| 64 | +type partialLengthReader struct { |
| 65 | + r io.Reader |
| 66 | + remaining int64 |
| 67 | + isPartial bool |
| 68 | +} |
| 69 | + |
| 70 | +func (r *partialLengthReader) Read(p []byte) (n int, err os.Error) { |
| 71 | + for r.remaining == 0 { |
| 72 | + if !r.isPartial { |
| 73 | + return 0, os.EOF |
| 74 | + } |
| 75 | + r.remaining, r.isPartial, err = readLength(r.r) |
| 76 | + if err != nil { |
| 77 | + return 0, err |
| 78 | + } |
| 79 | + } |
| 80 | + |
| 81 | + toRead := int64(len(p)) |
| 82 | + if toRead > r.remaining { |
| 83 | + toRead = r.remaining |
| 84 | + } |
| 85 | + |
| 86 | + n, err = r.r.Read(p[:int(toRead)]) |
| 87 | + r.remaining -= int64(n) |
| 88 | + if n < int(toRead) && err == os.EOF { |
| 89 | + err = io.ErrUnexpectedEOF |
| 90 | + } |
| 91 | + return |
| 92 | +} |
| 93 | + |
| 94 | +// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the |
| 95 | +// underlying Reader returns EOF before the limit has been reached. |
| 96 | +type spanReader struct { |
| 97 | + r io.Reader |
| 98 | + n int64 |
| 99 | +} |
| 100 | + |
| 101 | +func (l *spanReader) Read(p []byte) (n int, err os.Error) { |
| 102 | + if l.n <= 0 { |
| 103 | + return 0, os.EOF |
| 104 | + } |
| 105 | + if int64(len(p)) > l.n { |
| 106 | + p = p[0:l.n] |
| 107 | + } |
| 108 | + n, err = l.r.Read(p) |
| 109 | + l.n -= int64(n) |
| 110 | + if l.n > 0 && err == os.EOF { |
| 111 | + err = io.ErrUnexpectedEOF |
| 112 | + } |
| 113 | + return |
| 114 | +} |
| 115 | + |
| 116 | +// readHeader parses a packet header and returns an io.Reader which will return |
| 117 | +// the contents of the packet. See RFC 4880, section 4.2. |
| 118 | +func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err os.Error) { |
| 119 | + var buf [4]byte |
| 120 | + _, err = io.ReadFull(r, buf[:1]) |
| 121 | + if err != nil { |
| 122 | + return |
| 123 | + } |
| 124 | + if buf[0]&0x80 == 0 { |
| 125 | + err = error.StructuralError("tag byte does not have MSB set") |
| 126 | + return |
| 127 | + } |
| 128 | + if buf[0]&0x40 == 0 { |
| 129 | + // Old format packet |
| 130 | + tag = packetType((buf[0] & 0x3f) >> 2) |
| 131 | + lengthType := buf[0] & 3 |
| 132 | + if lengthType == 3 { |
| 133 | + length = -1 |
| 134 | + contents = r |
| 135 | + return |
| 136 | + } |
| 137 | + lengthBytes := 1 << lengthType |
| 138 | + _, err = readFull(r, buf[0:lengthBytes]) |
| 139 | + if err != nil { |
| 140 | + return |
| 141 | + } |
| 142 | + for i := 0; i < lengthBytes; i++ { |
| 143 | + length <<= 8 |
| 144 | + length |= int64(buf[i]) |
| 145 | + } |
| 146 | + contents = &spanReader{r, length} |
| 147 | + return |
| 148 | + } |
| 149 | + |
| 150 | + // New format packet |
| 151 | + tag = packetType(buf[0] & 0x3f) |
| 152 | + length, isPartial, err := readLength(r) |
| 153 | + if err != nil { |
| 154 | + return |
| 155 | + } |
| 156 | + if isPartial { |
| 157 | + contents = &partialLengthReader{ |
| 158 | + remaining: length, |
| 159 | + isPartial: true, |
| 160 | + r: r, |
| 161 | + } |
| 162 | + length = -1 |
| 163 | + } else { |
| 164 | + contents = &spanReader{r, length} |
| 165 | + } |
| 166 | + return |
| 167 | +} |
| 168 | + |
| 169 | +// serialiseHeader writes an OpenPGP packet header to w. See RFC 4880, section |
| 170 | +// 4.2. |
| 171 | +func serialiseHeader(w io.Writer, ptype packetType, length int) (err os.Error) { |
| 172 | + var buf [5]byte |
| 173 | + var n int |
| 174 | + |
| 175 | + buf[0] = 0x80 | 0x40 | byte(ptype) |
| 176 | + if length < 192 { |
| 177 | + buf[1] = byte(length) |
| 178 | + n = 2 |
| 179 | + } else if length < 8384 { |
| 180 | + length -= 192 |
| 181 | + buf[1] = byte(length >> 8) |
| 182 | + buf[2] = byte(length) |
| 183 | + n = 3 |
| 184 | + } else { |
| 185 | + buf[0] = 255 |
| 186 | + buf[1] = byte(length >> 24) |
| 187 | + buf[2] = byte(length >> 16) |
| 188 | + buf[3] = byte(length >> 8) |
| 189 | + buf[4] = byte(length) |
| 190 | + n = 5 |
| 191 | + } |
| 192 | + |
| 193 | + _, err = w.Write(buf[:n]) |
| 194 | + return |
| 195 | +} |
| 196 | + |
| 197 | +// Packet represents an OpenPGP packet. Users are expected to try casting |
| 198 | +// instances of this interface to specific packet types. |
| 199 | +type Packet interface { |
| 200 | + parse(io.Reader) os.Error |
| 201 | +} |
| 202 | + |
| 203 | +// consumeAll reads from the given Reader until error, returning the number of |
| 204 | +// bytes read. |
| 205 | +func consumeAll(r io.Reader) (n int64, err os.Error) { |
| 206 | + var m int |
| 207 | + var buf [1024]byte |
| 208 | + |
| 209 | + for { |
| 210 | + m, err = r.Read(buf[:]) |
| 211 | + n += int64(m) |
| 212 | + if err == os.EOF { |
| 213 | + err = nil |
| 214 | + return |
| 215 | + } |
| 216 | + if err != nil { |
| 217 | + return |
| 218 | + } |
| 219 | + } |
| 220 | + |
| 221 | + panic("unreachable") |
| 222 | +} |
| 223 | + |
| 224 | +// packetType represents the numeric ids of the different OpenPGP packet types. See |
| 225 | +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2 |
| 226 | +type packetType uint8 |
| 227 | + |
| 228 | +const ( |
| 229 | + packetTypeEncryptedKey packetType = 1 |
| 230 | + packetTypeSignature packetType = 2 |
| 231 | + packetTypeSymmetricKeyEncrypted packetType = 3 |
| 232 | + packetTypeOnePassSignature packetType = 4 |
| 233 | + packetTypePrivateKey packetType = 5 |
| 234 | + packetTypePublicKey packetType = 6 |
| 235 | + packetTypePrivateSubkey packetType = 7 |
| 236 | + packetTypeCompressed packetType = 8 |
| 237 | + packetTypeSymmetricallyEncrypted packetType = 9 |
| 238 | + packetTypeLiteralData packetType = 11 |
| 239 | + packetTypeUserId packetType = 13 |
| 240 | + packetTypePublicSubkey packetType = 14 |
| 241 | + packetTypeSymmetricallyEncryptedMDC packetType = 18 |
| 242 | +) |
| 243 | + |
| 244 | +// Read reads a single OpenPGP packet from the given io.Reader. If there is an |
| 245 | +// error parsing a packet, the whole packet is consumed from the input. |
| 246 | +func Read(r io.Reader) (p Packet, err os.Error) { |
| 247 | + tag, _, contents, err := readHeader(r) |
| 248 | + if err != nil { |
| 249 | + return |
| 250 | + } |
| 251 | + |
| 252 | + switch tag { |
| 253 | + case packetTypeEncryptedKey: |
| 254 | + p = new(EncryptedKey) |
| 255 | + case packetTypeSignature: |
| 256 | + p = new(Signature) |
| 257 | + case packetTypeSymmetricKeyEncrypted: |
| 258 | + p = new(SymmetricKeyEncrypted) |
| 259 | + case packetTypeOnePassSignature: |
| 260 | + p = new(OnePassSignature) |
| 261 | + case packetTypePrivateKey, packetTypePrivateSubkey: |
| 262 | + pk := new(PrivateKey) |
| 263 | + if tag == packetTypePrivateSubkey { |
| 264 | + pk.IsSubKey = true |
| 265 | + } |
| 266 | + p = pk |
| 267 | + case packetTypePublicKey, packetTypePublicSubkey: |
| 268 | + pk := new(PublicKey) |
| 269 | + if tag == packetTypePublicSubkey { |
| 270 | + pk.IsSubKey = true |
| 271 | + } |
| 272 | + p = pk |
| 273 | + case packetTypeCompressed: |
| 274 | + p = new(Compressed) |
| 275 | + case packetTypeSymmetricallyEncrypted: |
| 276 | + p = new(SymmetricallyEncrypted) |
| 277 | + case packetTypeLiteralData: |
| 278 | + p = new(LiteralData) |
| 279 | + case packetTypeUserId: |
| 280 | + p = new(UserId) |
| 281 | + case packetTypeSymmetricallyEncryptedMDC: |
| 282 | + se := new(SymmetricallyEncrypted) |
| 283 | + se.MDC = true |
| 284 | + p = se |
| 285 | + default: |
| 286 | + err = error.UnknownPacketTypeError(tag) |
| 287 | + } |
| 288 | + if p != nil { |
| 289 | + err = p.parse(contents) |
| 290 | + } |
| 291 | + if err != nil { |
| 292 | + consumeAll(contents) |
| 293 | + } |
| 294 | + return |
| 295 | +} |
| 296 | + |
| 297 | +// SignatureType represents the different semantic meanings of an OpenPGP |
| 298 | +// signature. See RFC 4880, section 5.2.1. |
| 299 | +type SignatureType uint8 |
| 300 | + |
| 301 | +const ( |
| 302 | + SigTypeBinary SignatureType = 0 |
| 303 | + SigTypeText SignatureType = 1 |
| 304 | + SigTypeGenericCert = 0x10 |
| 305 | + SigTypePersonaCert = 0x11 |
| 306 | + SigTypeCasualCert = 0x12 |
| 307 | + SigTypePositiveCert = 0x13 |
| 308 | + SigTypeSubkeyBinding = 0x18 |
| 309 | +) |
| 310 | + |
| 311 | +// PublicKeyAlgorithm represents the different public key system specified for |
| 312 | +// OpenPGP. See |
| 313 | +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12 |
| 314 | +type PublicKeyAlgorithm uint8 |
| 315 | + |
| 316 | +const ( |
| 317 | + PubKeyAlgoRSA PublicKeyAlgorithm = 1 |
| 318 | + PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 |
| 319 | + PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3 |
| 320 | + PubKeyAlgoElgamal PublicKeyAlgorithm = 16 |
| 321 | + PubKeyAlgoDSA PublicKeyAlgorithm = 17 |
| 322 | +) |
| 323 | + |
| 324 | +// CipherFunction represents the different block ciphers specified for OpenPGP. See |
| 325 | +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 |
| 326 | +type CipherFunction uint8 |
| 327 | + |
| 328 | +const ( |
| 329 | + CipherCAST5 = 3 |
| 330 | + CipherAES128 = 7 |
| 331 | + CipherAES192 = 8 |
| 332 | + CipherAES256 = 9 |
| 333 | +) |
| 334 | + |
| 335 | +// keySize returns the key size, in bytes, of cipher. |
| 336 | +func (cipher CipherFunction) keySize() int { |
| 337 | + switch cipher { |
| 338 | + case CipherCAST5: |
| 339 | + return cast5.KeySize |
| 340 | + case CipherAES128: |
| 341 | + return 16 |
| 342 | + case CipherAES192: |
| 343 | + return 24 |
| 344 | + case CipherAES256: |
| 345 | + return 32 |
| 346 | + } |
| 347 | + return 0 |
| 348 | +} |
| 349 | + |
| 350 | +// blockSize returns the block size, in bytes, of cipher. |
| 351 | +func (cipher CipherFunction) blockSize() int { |
| 352 | + switch cipher { |
| 353 | + case CipherCAST5: |
| 354 | + return 8 |
| 355 | + case CipherAES128, CipherAES192, CipherAES256: |
| 356 | + return 16 |
| 357 | + } |
| 358 | + return 0 |
| 359 | +} |
| 360 | + |
| 361 | +// new returns a fresh instance of the given cipher. |
| 362 | +func (cipher CipherFunction) new(key []byte) (block cipher.Block) { |
| 363 | + switch cipher { |
| 364 | + case CipherCAST5: |
| 365 | + block, _ = cast5.NewCipher(key) |
| 366 | + case CipherAES128, CipherAES192, CipherAES256: |
| 367 | + block, _ = aes.NewCipher(key) |
| 368 | + } |
| 369 | + return |
| 370 | +} |
| 371 | + |
| 372 | +// readMPI reads a big integer from r. The bit length returned is the bit |
| 373 | +// length that was specified in r. This is preserved so that the integer can be |
| 374 | +// reserialised exactly. |
| 375 | +func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err os.Error) { |
| 376 | + var buf [2]byte |
| 377 | + _, err = readFull(r, buf[0:]) |
| 378 | + if err != nil { |
| 379 | + return |
| 380 | + } |
| 381 | + bitLength = uint16(buf[0])<<8 | uint16(buf[1]) |
| 382 | + numBytes := (int(bitLength) + 7) / 8 |
| 383 | + mpi = make([]byte, numBytes) |
| 384 | + _, err = readFull(r, mpi) |
| 385 | + return |
| 386 | +} |
| 387 | + |
| 388 | +// writeMPI serialises a big integer to r. |
| 389 | +func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err os.Error) { |
| 390 | + _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) |
| 391 | + if err == nil { |
| 392 | + _, err = w.Write(mpiBytes) |
| 393 | + } |
| 394 | + return |
| 395 | +} |
0 commit comments