Example #1
0
// Too complicated to be inline
Result
ReadTagAndGetValue(Reader& input, /*out*/ uint8_t& tag, /*out*/ Input& value)
{
  Result rv;

  rv = input.Read(tag);
  if (rv != Success) {
    return rv;
  }
  if ((tag & 0x1F) == 0x1F) {
    return Result::ERROR_BAD_DER; // high tag number form not allowed
  }

  uint16_t length;

  // The short form of length is a single byte with the high order bit set
  // to zero. The long form of length is one byte with the high order bit
  // set, followed by N bytes, where N is encoded in the lowest 7 bits of
  // the first byte.
  uint8_t length1;
  rv = input.Read(length1);
  if (rv != Success) {
    return rv;
  }
  if (!(length1 & 0x80)) {
    length = length1;
  } else if (length1 == 0x81) {
    uint8_t length2;
    rv = input.Read(length2);
    if (rv != Success) {
      return rv;
    }
    if (length2 < 128) {
      // Not shortest possible encoding
      return Result::ERROR_BAD_DER;
    }
    length = length2;
  } else if (length1 == 0x82) {
    rv = input.Read(length);
    if (rv != Success) {
      return rv;
    }
    if (length < 256) {
      // Not shortest possible encoding
      return Result::ERROR_BAD_DER;
    }
  } else {
    // We don't support lengths larger than 2^16 - 1.
    return Result::ERROR_BAD_DER;
  }

  return input.Skip(length, value);
}