예제 #1
0
static GcrDataError
read_openpgp_packet (const guchar **at,
                     const guchar *end,
                     guint8 *pkt_type,
                     gsize *length)
{
	gboolean new_ctb;
	guint8 ctb;
	gboolean ret;

	if (!read_byte (at, end, &ctb))
		return GCR_ERROR_UNRECOGNIZED;
	if (!(ctb & 0x80))
		return GCR_ERROR_UNRECOGNIZED;

	/* RFC2440 packet format. */
	if (ctb & 0x40) {
		*pkt_type = ctb & 0x3f;
		new_ctb = TRUE;

	/* the old RFC1991 packet format. */
	} else {
		*pkt_type = ctb & 0x3f;
		*pkt_type >>= 2;
		new_ctb = FALSE;
	}

	if (*pkt_type > 63)
		return GCR_ERROR_UNRECOGNIZED;

	if (new_ctb)
		ret = read_new_length (at, end, length);
	else
		ret = read_old_length (at, end, ctb, length);
	if (!ret)
		return GCR_ERROR_UNRECOGNIZED;

	if ((*at) + *length > end)
		return GCR_ERROR_FAILURE;

	return GCR_SUCCESS;
}
예제 #2
0
/**
 * cdk_pkt_read:
 * @inp: the input stream
 * @pkt: allocated packet handle to store the packet
 *
 * Parse the next packet on the @inp stream and return its contents in @pkt.
 **/
cdk_error_t
cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt)
{
  int ctb, is_newctb;
  int pkttype;
  size_t pktlen = 0, pktsize = 0, is_partial = 0;
  cdk_error_t rc;

  if (!inp || !pkt)
    return CDK_Inv_Value;

  ctb = cdk_stream_getc (inp);
  if (cdk_stream_eof (inp) || ctb == EOF)
    return CDK_EOF;
  else if (!ctb)
    return CDK_Inv_Packet;

  pktsize++;
  if (!(ctb & 0x80))
    {
      _cdk_log_info ("cdk_pkt_read: no openpgp data found. "
		     "(ctb=%02X; fpos=%02X)\n", ctb, cdk_stream_tell (inp));
      return CDK_Inv_Packet;
    }

  if (ctb & 0x40)		/* RFC2440 packet format. */
    {
      pkttype = ctb & 0x3f;
      is_newctb = 1;
    }
  else				/* the old RFC1991 packet format. */
    {
      pkttype = ctb & 0x3f;
      pkttype >>= 2;
      is_newctb = 0;
    }

  if (pkttype > 63)
    {
      _cdk_log_info ("cdk_pkt_read: unknown type %d\n", pkttype);
      return CDK_Inv_Packet;
    }

  if (is_newctb)
    read_new_length (inp, &pktlen, &pktsize, &is_partial);
  else
    read_old_length (inp, ctb, &pktlen, &pktsize);

  pkt->pkttype = pkttype;
  pkt->pktlen = pktlen;
  pkt->pktsize = pktsize + pktlen;
  pkt->old_ctb = is_newctb ? 0 : 1;

  rc = 0;
  switch (pkt->pkttype)
    {
    case CDK_PKT_ATTRIBUTE:
      pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
				     + pkt->pktlen + 16 + 1);
      if (!pkt->pkt.user_id)
	return CDK_Out_Of_Core;
      pkt->pkt.user_id->name = (char*)pkt->pkt.user_id + sizeof(*pkt->pkt.user_id);

      rc = read_attribute (inp, pktlen, pkt->pkt.user_id);
      pkt->pkttype = CDK_PKT_ATTRIBUTE;
      break;

    case CDK_PKT_USER_ID:
      pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
				     + pkt->pktlen + 1);
      if (!pkt->pkt.user_id)
	return CDK_Out_Of_Core;
      pkt->pkt.user_id->name = (char*)pkt->pkt.user_id + sizeof(*pkt->pkt.user_id);
      rc = read_user_id (inp, pktlen, pkt->pkt.user_id);
      break;

    case CDK_PKT_PUBLIC_KEY:
      pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
      if (!pkt->pkt.public_key)
	return CDK_Out_Of_Core;
      rc = read_public_key (inp, pktlen, pkt->pkt.public_key);
      break;

    case CDK_PKT_PUBLIC_SUBKEY:
      pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
      if (!pkt->pkt.public_key)
	return CDK_Out_Of_Core;
      rc = read_public_subkey (inp, pktlen, pkt->pkt.public_key);
      break;

    case CDK_PKT_SECRET_KEY:
      pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
      if (!pkt->pkt.secret_key)
	return CDK_Out_Of_Core;
      pkt->pkt.secret_key->pk = cdk_calloc (1,
					    sizeof *pkt->pkt.secret_key->pk);
      if (!pkt->pkt.secret_key->pk)
	return CDK_Out_Of_Core;
      rc = read_secret_key (inp, pktlen, pkt->pkt.secret_key);
      break;

    case CDK_PKT_SECRET_SUBKEY:
      pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
      if (!pkt->pkt.secret_key)
	return CDK_Out_Of_Core;
      pkt->pkt.secret_key->pk = cdk_calloc (1,
					    sizeof *pkt->pkt.secret_key->pk);
      if (!pkt->pkt.secret_key->pk)
	return CDK_Out_Of_Core;
      rc = read_secret_subkey (inp, pktlen, pkt->pkt.secret_key);
      break;

    case CDK_PKT_LITERAL:
      pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal);
      if (!pkt->pkt.literal)
	return CDK_Out_Of_Core;
      rc = read_literal (inp, pktlen, &pkt->pkt.literal, is_partial);
      break;

    case CDK_PKT_ONEPASS_SIG:
      pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig);
      if (!pkt->pkt.onepass_sig)
	return CDK_Out_Of_Core;
      rc = read_onepass_sig (inp, pktlen, pkt->pkt.onepass_sig);
      break;

    case CDK_PKT_SIGNATURE:
      pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
      if (!pkt->pkt.signature)
	return CDK_Out_Of_Core;
      rc = read_signature (inp, pktlen, pkt->pkt.signature);
      break;

    case CDK_PKT_PUBKEY_ENC:
      pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
      if (!pkt->pkt.pubkey_enc)
	return CDK_Out_Of_Core;
      rc = read_pubkey_enc (inp, pktlen, pkt->pkt.pubkey_enc);
      break;

    case CDK_PKT_COMPRESSED:
      pkt->pkt.compressed = cdk_calloc (1, sizeof *pkt->pkt.compressed);
      if (!pkt->pkt.compressed)
	return CDK_Out_Of_Core;
      rc = read_compressed (inp, pktlen, pkt->pkt.compressed);
      break;

    case CDK_PKT_MDC:
      pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
      if (!pkt->pkt.mdc)
	return CDK_Out_Of_Core;
      rc = read_mdc (inp, pkt->pkt.mdc);
      break;

    default:
      /* Skip all packets we don't understand */
      skip_packet (inp, pktlen);
      break;
    }

  return rc;
}