OpenPGP packet header decode (RFC 4880 §4.2). Returns the tag and body length and sets bodyOffset to the start of the body relative to packetStart. Returns false on malformed or partial-length packets (we don't need to support partial-length for a primary key).
| 353 | // bodyOffset to the start of the body relative to packetStart. Returns false on malformed |
| 354 | // or partial-length packets (we don't need to support partial-length for a primary key). |
| 355 | bool readPacketHeader(const std::vector<uint8_t> &data, size_t packetStart, |
| 356 | uint8_t &tag, size_t &bodyOffset, size_t &bodyLen) { |
| 357 | if (packetStart >= data.size()) { |
| 358 | return false; |
| 359 | } |
| 360 | const uint8_t h = data[packetStart]; |
| 361 | if ((h & 0x80) == 0) { |
| 362 | return false; // bit 7 must be set |
| 363 | } |
| 364 | if (h & 0x40) { |
| 365 | // New-format packet. |
| 366 | tag = h & 0x3F; |
| 367 | if (packetStart + 1 >= data.size()) { |
| 368 | return false; |
| 369 | } |
| 370 | const uint8_t l0 = data[packetStart + 1]; |
| 371 | if (l0 < 192) { |
| 372 | bodyLen = l0; |
| 373 | bodyOffset = packetStart + 2; |
| 374 | } else if (l0 < 224) { |
| 375 | if (packetStart + 2 >= data.size()) { |
| 376 | return false; |
| 377 | } |
| 378 | bodyLen = ((l0 - 192) << 8) + data[packetStart + 2] + 192; |
| 379 | bodyOffset = packetStart + 3; |
| 380 | } else if (l0 == 255) { |
| 381 | if (packetStart + 5 >= data.size()) { |
| 382 | return false; |
| 383 | } |
| 384 | bodyLen = (static_cast<size_t>(data[packetStart + 2]) << 24) | |
| 385 | (static_cast<size_t>(data[packetStart + 3]) << 16) | |
| 386 | (static_cast<size_t>(data[packetStart + 4]) << 8) | |
| 387 | static_cast<size_t>(data[packetStart + 5]); |
| 388 | bodyOffset = packetStart + 6; |
| 389 | } else { |
| 390 | // Partial-length packet — would only appear for streamed data, not a key. |
| 391 | return false; |
| 392 | } |
| 393 | } else { |
| 394 | // Old-format packet. |
| 395 | tag = (h >> 2) & 0x0F; |
| 396 | const uint8_t lenType = h & 0x03; |
| 397 | switch (lenType) { |
| 398 | case 0: |
| 399 | if (packetStart + 1 >= data.size()) { |
| 400 | return false; |
| 401 | } |
| 402 | bodyLen = data[packetStart + 1]; |
| 403 | bodyOffset = packetStart + 2; |
| 404 | break; |
| 405 | case 1: |
| 406 | if (packetStart + 2 >= data.size()) { |
| 407 | return false; |
| 408 | } |
| 409 | bodyLen = (static_cast<size_t>(data[packetStart + 1]) << 8) | |
| 410 | static_cast<size_t>(data[packetStart + 2]); |
| 411 | bodyOffset = packetStart + 3; |
| 412 | break; |
no test coverage detected