Blob Blame History Raw
diff --git a/lib/opencdk/kbnode.c b/lib/opencdk/kbnode.c
index c28cb34..f865b16 100644
--- a/lib/opencdk/kbnode.c
+++ b/lib/opencdk/kbnode.c
@@ -369,12 +369,14 @@ cdk_packet_t cdk_kbnode_get_packet(cdk_kbnode_t node)
  * @armor: whether base64 or not
  * @buf: the buffer which stores the key sequence
  * @buflen: the length of the buffer
+ * @public: non-zero if reading a public key
  *
  * Tries to read a key node from the memory buffer @buf.
  **/
 cdk_error_t
 cdk_kbnode_read_from_mem(cdk_kbnode_t * ret_node,
-			 int armor, const byte * buf, size_t buflen)
+			 int armor, const byte * buf, size_t buflen,
+			 unsigned public)
 {
 	cdk_stream_t inp;
 	cdk_error_t rc;
@@ -393,7 +395,7 @@ cdk_kbnode_read_from_mem(cdk_kbnode_t * ret_node,
 	if (armor)
 		cdk_stream_set_armor_flag(inp, 0);
 
-	rc = cdk_keydb_get_keyblock(inp, ret_node);
+	rc = cdk_keydb_get_keyblock(inp, ret_node, public);
 	if (rc)
 		gnutls_assert();
 	cdk_stream_close(inp);
diff --git a/lib/opencdk/keydb.c b/lib/opencdk/keydb.c
index 64eebf0..9112d9a 100644
--- a/lib/opencdk/keydb.c
+++ b/lib/opencdk/keydb.c
@@ -108,7 +108,7 @@ static cdk_error_t keydb_idx_build(const char *file)
 	while (!cdk_stream_eof(inp)) {
 		off_t pos = cdk_stream_tell(inp);
 
-		rc = cdk_pkt_read(inp, pkt);
+		rc = cdk_pkt_read(inp, pkt, 1);
 		if (rc) {
 			_cdk_log_debug
 			    ("index build failed packet off=%lu\n",
@@ -816,7 +816,7 @@ cdk_keydb_search(cdk_keydb_search_t st, cdk_keydb_hd_t hd,
 
 		pos = cdk_stream_tell(kr);
 
-		rc = cdk_keydb_get_keyblock(kr, &knode);
+		rc = cdk_keydb_get_keyblock(kr, &knode, 1);
 
 		if (rc) {
 			if (rc == CDK_EOF)
@@ -1679,7 +1679,7 @@ add_key_usage(cdk_kbnode_t knode, u32 keyid[2], unsigned int usage)
 }
 
 cdk_error_t
-cdk_keydb_get_keyblock(cdk_stream_t inp, cdk_kbnode_t * r_knode)
+cdk_keydb_get_keyblock(cdk_stream_t inp, cdk_kbnode_t * r_knode, unsigned public)
 {
 	cdk_packet_t pkt;
 	cdk_kbnode_t knode, node;
@@ -1706,7 +1706,7 @@ cdk_keydb_get_keyblock(cdk_stream_t inp, cdk_kbnode_t * r_knode)
 	while (!cdk_stream_eof(inp)) {
 		cdk_pkt_new(&pkt);
 		old_off = cdk_stream_tell(inp);
-		rc = cdk_pkt_read(inp, pkt);
+		rc = cdk_pkt_read(inp, pkt, public);
 		if (rc) {
 			cdk_pkt_release(pkt);
 			if (rc == CDK_EOF)
@@ -2126,7 +2126,7 @@ cdk_error_t cdk_keydb_check_sk(cdk_keydb_hd_t hd, u32 * keyid)
 		return rc;
 	}
 	cdk_pkt_new(&pkt);
-	while (!cdk_pkt_read(db, pkt)) {
+	while (!cdk_pkt_read(db, pkt, 0)) {
 		if (pkt->pkttype != CDK_PKT_SECRET_KEY &&
 		    pkt->pkttype != CDK_PKT_SECRET_SUBKEY) {
 			cdk_pkt_free(pkt);
@@ -2241,14 +2241,14 @@ cdk_error_t cdk_listkey_next(cdk_listkey_t ctx, cdk_kbnode_t * ret_key)
 	}
 
 	if (ctx->type && ctx->u.patt[0] == '*')
-		return cdk_keydb_get_keyblock(ctx->inp, ret_key);
+		return cdk_keydb_get_keyblock(ctx->inp, ret_key, 1);
 	else if (ctx->type) {
 		cdk_kbnode_t node;
 		struct cdk_keydb_search_s ks;
 		cdk_error_t rc;
 
 		for (;;) {
-			rc = cdk_keydb_get_keyblock(ctx->inp, &node);
+			rc = cdk_keydb_get_keyblock(ctx->inp, &node, 1);
 			if (rc) {
 				gnutls_assert();
 				return rc;
diff --git a/lib/opencdk/literal.c b/lib/opencdk/literal.c
index 7b4baec..6996774 100644
--- a/lib/opencdk/literal.c
+++ b/lib/opencdk/literal.c
@@ -67,7 +67,7 @@ static cdk_error_t literal_decode(void *data, FILE * in, FILE * out)
 		return rc;
 
 	cdk_pkt_new(&pkt);
-	rc = cdk_pkt_read(si, pkt);
+	rc = cdk_pkt_read(si, pkt, 1);
 	if (rc || pkt->pkttype != CDK_PKT_LITERAL) {
 		cdk_pkt_release(pkt);
 		cdk_stream_close(si);
diff --git a/lib/opencdk/opencdk.h b/lib/opencdk/opencdk.h
index c06b749..d95cc32 100644
--- a/lib/opencdk/opencdk.h
+++ b/lib/opencdk/opencdk.h
@@ -553,7 +553,7 @@ extern "C" {
 	void cdk_pkt_release(cdk_packet_t pkt);
 
 /* Read or write the given output from or to the stream. */
-	cdk_error_t cdk_pkt_read(cdk_stream_t inp, cdk_packet_t pkt);
+	cdk_error_t cdk_pkt_read(cdk_stream_t inp, cdk_packet_t pkt, unsigned public);
 	cdk_error_t cdk_pkt_write(cdk_stream_t out, cdk_packet_t pkt);
 
 /* Sub packet routines */
@@ -814,7 +814,8 @@ extern "C" {
 /* Try to read the next key block from the given input stream.
    The key will be returned in @RET_KEY on success. */
 	cdk_error_t cdk_keydb_get_keyblock(cdk_stream_t inp,
-					   cdk_kbnode_t * ret_key);
+					   cdk_kbnode_t * ret_key,
+					   unsigned public);
 
 /* Rebuild the key db index if possible. */
 	cdk_error_t cdk_keydb_idx_rebuild(cdk_keydb_hd_t db,
@@ -848,7 +849,7 @@ extern "C" {
 	cdk_error_t cdk_kbnode_read_from_mem(cdk_kbnode_t * ret_node,
 					     int armor,
 					     const unsigned char *buf,
-					     size_t buflen);
+					     size_t buflen, unsigned public);
 	cdk_error_t cdk_kbnode_write_to_mem(cdk_kbnode_t node,
 					    unsigned char *buf,
 					    size_t * r_nbytes);
diff --git a/lib/opencdk/read-packet.c b/lib/opencdk/read-packet.c
index 7a474ff..72624d0 100644
--- a/lib/opencdk/read-packet.c
+++ b/lib/opencdk/read-packet.c
@@ -571,6 +571,9 @@ read_user_id(cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t user_id)
 }
 
 
+#define MAX_PACKET_LEN (1<<24)
+
+
 static cdk_error_t
 read_subpkt(cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes)
 {
@@ -610,6 +613,10 @@ read_subpkt(cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes)
 	else
 		return CDK_Inv_Packet;
 
+	if (size >= MAX_PACKET_LEN) {
+		return CDK_Inv_Packet;
+	}
+
 	node = cdk_subpkt_new(size);
 	if (!node)
 		return CDK_Out_Of_Core;
@@ -958,7 +965,7 @@ static cdk_error_t skip_packet(cdk_stream_t inp, size_t pktlen)
  *
  * 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)
+cdk_error_t cdk_pkt_read(cdk_stream_t inp, cdk_packet_t pkt, unsigned public)
 {
 	int ctb, is_newctb;
 	int pkttype;
@@ -1058,6 +1065,10 @@ cdk_error_t cdk_pkt_read(cdk_stream_t inp, cdk_packet_t pkt)
 		break;
 
 	case CDK_PKT_SECRET_KEY:
+		if (public) {
+			/* read secret key when expecting public */
+			return gnutls_assert_val(CDK_Inv_Packet);
+		}
 		pkt->pkt.secret_key =
 		    cdk_calloc(1, sizeof *pkt->pkt.secret_key);
 		if (!pkt->pkt.secret_key)
@@ -1073,6 +1084,10 @@ cdk_error_t cdk_pkt_read(cdk_stream_t inp, cdk_packet_t pkt)
 		break;
 
 	case CDK_PKT_SECRET_SUBKEY:
+		if (public) {
+			/* read secret key when expecting public */
+			return gnutls_assert_val(CDK_Inv_Packet);
+		}
 		pkt->pkt.secret_key =
 		    cdk_calloc(1, sizeof *pkt->pkt.secret_key);
 		if (!pkt->pkt.secret_key)
diff --git a/lib/openpgp/gnutls_openpgp.c b/lib/openpgp/gnutls_openpgp.c
index 7c05e1f..192737f 100644
--- a/lib/openpgp/gnutls_openpgp.c
+++ b/lib/openpgp/gnutls_openpgp.c
@@ -479,7 +479,7 @@ int gnutls_openpgp_count_key_names(const gnutls_datum_t * cert)
 		return 0;
 	}
 
-	if (cdk_kbnode_read_from_mem(&knode, 0, cert->data, cert->size)) {
+	if (cdk_kbnode_read_from_mem(&knode, 0, cert->data, cert->size, 1)) {
 		gnutls_assert();
 		return 0;
 	}
diff --git a/lib/openpgp/pgp.c b/lib/openpgp/pgp.c
index d5ef272..77e57ab 100644
--- a/lib/openpgp/pgp.c
+++ b/lib/openpgp/pgp.c
@@ -99,7 +99,7 @@ gnutls_openpgp_crt_import(gnutls_openpgp_crt_t key,
 		armor = 1;
 
 	rc = cdk_kbnode_read_from_mem(&key->knode, armor, data->data,
-				      data->size);
+				      data->size, 1);
 	if (rc) {
 		rc = _gnutls_map_cdk_rc(rc);
 		gnutls_assert();
diff --git a/lib/openpgp/privkey.c b/lib/openpgp/privkey.c
index 6aa6fb5..81ec3ab 100644
--- a/lib/openpgp/privkey.c
+++ b/lib/openpgp/privkey.c
@@ -186,7 +186,7 @@ gnutls_openpgp_privkey_import(gnutls_openpgp_privkey_t key,
 		armor = 1;
 
 	rc = cdk_kbnode_read_from_mem(&key->knode, armor, data->data,
-				      data->size);
+				      data->size, 0);
 	if (rc != 0) {
 		rc = _gnutls_map_cdk_rc(rc);
 		gnutls_assert();