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; }
/** * 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; }