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();