aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2026-10-23 15:07:00 +0200
committerWerner Koch <[email protected]>2026-10-23 15:32:21 +0200
commit9fbeb5897f8b8e9cfae7f65eb447813a40329d62 (patch)
tree21368eef0fbcb4d729150472e55b7544edd6f9fe
parentscd: Add askpin_inquiry for app-openpgp, not enabled for now. (diff)
downloadgnupg-master.tar.gz
gnupg-master.zip
common: Allow the use of the newer ksba_parser_t functions.HEADmaster
* common/tlv.h: Prepare for use obn ksba 1.9.0 functions. * common/tlv-parser.c [KSBA_VERSION_NUMBER]: Add wrappers for using the ksba versions of the code.
-rw-r--r--common/tlv-parser.c240
-rw-r--r--common/tlv.h8
2 files changed, 247 insertions, 1 deletions
diff --git a/common/tlv-parser.c b/common/tlv-parser.c
index 5c464f4cd..dc970be54 100644
--- a/common/tlv-parser.c
+++ b/common/tlv-parser.c
@@ -28,9 +28,245 @@
#include "util.h"
#include "tlv.h"
+/* For older KSBA versions we keep our own code. That code has been
+ * slighly modified migrated to KSBA 1.9.0 so that we only need
+ * wrappers in that case. */
+#if KSBA_VERSION_NUMBER >= 0x010900 /* 1.9.0 */
-#define TLV_MAX_DEPTH 25
+void
+_tlv_parser_dump_tag (const char *text, int lno, tlv_parser_t tlv)
+{
+ (void)text;
+ (void)lno;
+ ksba_parser_setflag (tlv, KSBA_PARSER_DUMPTAG);
+}
+
+
+void
+_tlv_parser_dump_state (const char *text, const char *text2,
+ int lno, tlv_parser_t tlv)
+{
+ (void)text;
+ (void)text2;
+ (void)lno;
+ ksba_parser_setflag (tlv, KSBA_PARSER_DUMPSTATE);
+}
+
+
+/* Public version of parse_tag. */
+gpg_error_t
+tlv_parse_tag (unsigned char const **buffer, size_t *size, struct tag_info *ti)
+{
+ struct ksba_tlv_s tlv;
+ gpg_error_t err;
+
+ err = ksba_parse_tag (buffer, size, &tlv, NULL);
+ ti->class = tlv.cls;
+ ti->is_constructed = tlv.cons;
+ ti->tag = tlv.tag;
+ ti->length = tlv.length;
+ ti->nhdr = tlv.nhdr;
+ ti->ndef = tlv.ndef;
+
+ return err;
+}
+
+
+/* Create a new TLV object. */
+tlv_parser_t
+_tlv_parser_new (const unsigned char *buffer, size_t bufsize,
+ int verbosity, tlv_parser_t lasttlv, int lno)
+{
+ return _ksba_parser_new (buffer, bufsize, verbosity, lasttlv, lno);
+}
+
+
+/* Free the TLV object and returns the last TLV object stored in this
+ * TLV. */
+tlv_parser_t
+_tlv_parser_release (tlv_parser_t tlv, int lno)
+{
+ return _ksba_parser_release (tlv, lno);
+}
+
+/* Parse the next tag and value. Also detect the end of a
+ * container. The caller should use the tlv_next macro. */
+gpg_error_t
+_tlv_parser_next (tlv_parser_t tlv, unsigned int flag, int lno)
+{
+ if (tlv && (flag & TLV_PARSER_FLAG_T5793))
+ ksba_parser_setflag (tlv, KSBA_PARSER_T5793);
+ return _ksba_parser_next (tlv, lno);
+}
+
+
+/* Return the current nesting level of the TLV object. */
+unsigned int
+tlv_parser_level (tlv_parser_t tlv)
+{
+ return ksba_parser_getnumber (tlv, KSBA_PARSER_LEVEL);
+}
+/* Returns the current offset of the parser. */
+size_t
+tlv_parser_offset (tlv_parser_t tlv)
+{
+ return ksba_parser_getnumber (tlv, KSBA_PARSER_OFFSET);
+}
+
+/* Return a string with the last function used. If TLV is NULL an
+ * empty string is returned. */
+const char *
+tlv_parser_lastfunc (tlv_parser_t tlv)
+{
+ return ksba_parser_getstring (tlv, KSBA_PARSER_LASTFUNC);
+}
+
+
+const char *
+tlv_parser_lasterrstr (tlv_parser_t tlv)
+{
+ return ksba_parser_getstring (tlv, KSBA_PARSER_LASTERR);
+}
+
+/* Set a flag to indicate that the last tlv_next has not yet been
+ * consumed. */
+void
+tlv_parser_set_pending (tlv_parser_t tlv)
+{
+ ksba_parser_setflag (tlv, KSBA_PARSER_PENDING);
+}
+
+
+/* Return the length of the last read tag. If with_header is 1 the
+ * lengtb of the header is added to the returned length. */
+size_t
+tlv_parser_tag_length (tlv_parser_t tlv, int with_header)
+{
+ if (with_header)
+ return ksba_parser_getnumber (tlv, KSBA_PARSER_TAGLENHDR);
+ else
+ return ksba_parser_getnumber (tlv, KSBA_PARSER_TAGLEN);
+}
+
+
+/* Skip over the value of the current tag. Does not yet work for ndef
+ * containers. */
+void
+tlv_parser_skip (tlv_parser_t tlv)
+{
+ ksba_parser_skip (tlv);
+}
+
+
+/* Expect that the current tag is a sequence and setup the context for
+ * processing. */
+gpg_error_t
+tlv_expect_sequence (tlv_parser_t tlv)
+{
+ return ksba_expect_sequence (tlv);
+}
+
+
+/* Expect that the current tag is a context tag and setup the context
+ * for processing. The tag of the context is returned at R_TAG. */
+gpg_error_t
+tlv_expect_context_tag (tlv_parser_t tlv, int *r_tag)
+{
+ return ksba_expect_context_tag (tlv, r_tag);
+}
+
+
+/* Expect that the current tag is a SET and setup the context for
+ * processing. */
+gpg_error_t
+tlv_expect_set (tlv_parser_t tlv)
+{
+ return ksba_expect_set (tlv);
+}
+
+
+/* Expect an object of CLASS with TAG and store its value at
+ * (R_DATA,R_DATALEN). Then skip over its value to the next tag.
+ * Note that the stored value is not allocated but points into
+ * TLV. */
+gpg_error_t
+tlv_expect_object (tlv_parser_t tlv, int class, int tag,
+ unsigned char const **r_data, size_t *r_datalen)
+{
+ return ksba_expect_object (tlv, class, tag, r_data, r_datalen);
+}
+
+
+/* Expect that the current tag is an object string and store its value
+ * at (R_DATA,R_DATALEN). Then skip over its value to the next tag.
+ * Note that the stored value are not allocated but point into TLV. */
+gpg_error_t
+tlv_expect_octet_string (tlv_parser_t tlv,
+ unsigned char const **r_data, size_t *r_datalen)
+{
+ return ksba_expect_octet_string (tlv, r_data, r_datalen);
+}
+
+
+/* Expect that the current tag is an integer and return its value at
+ * R_VALUE. Then skip over its value to the next tag. */
+gpg_error_t
+tlv_expect_integer (tlv_parser_t tlv, int *r_value)
+{
+ return ksba_expect_integer (tlv, r_value);
+}
+
+
+/* Variant of tlv_expect_integer which returns an MPI. If IGNORE_ZERO
+ * is set a value of 0 is ignored and R_VALUE not changed and the
+ * function returns GPG_ERR_FALSE. No check for negative encoded
+ * integers is done because the old code here worked the same and we
+ * can't foreclose invalid encoded PKCS#12 stuff - after all it is
+ * PKCS#12 see https://www.cs.auckland.ac.nz/~pgut001/pubs/pfx.html */
+#ifdef GCRYPT_VERSION
+gpg_error_t
+tlv_expect_mpinteger (tlv_parser_t tlv, int ignore_zero,
+ gcry_mpi_t *r_value)
+{
+ gpg_error_t err;
+ const unsigned char *p;
+ size_t n;
+
+ err = ksba_expect_object (tlv, KSBA_CLASS_UNIVERSAL, KSBA_TYPE_INTEGER,
+ &p, &n);
+ if (err)
+ return err;
+ if (ignore_zero && n == 1 && !*p)
+ return gpg_error (GPG_ERR_FALSE);
+
+ return gcry_mpi_scan (r_value, GCRYMPI_FMT_USG, p, n, NULL);
+}
+#endif /*GCRYPT_VERSION*/
+
+
+/* Expect that the current tag is an object id and store its value at
+ * (R_OID,R_OIDLEN). Then skip over its value to the next tag. Note
+ * that the stored value is not allocated but points into TLV. */
+gpg_error_t
+tlv_expect_object_id (tlv_parser_t tlv,
+ unsigned char const **r_oid, size_t *r_oidlen)
+{
+ return ksba_expect_object_id (tlv, r_oid, r_oidlen);
+}
+
+
+/* Expect a NULL tag. */
+gpg_error_t
+tlv_expect_null (tlv_parser_t tlv)
+{
+ return ksba_expect_null (tlv);
+}
+
+
+#else /* KSBA < 1.9.0 */
+
+#define TLV_MAX_DEPTH 25
/* An object to control the ASN.1 parsing. */
@@ -825,3 +1061,5 @@ cram_octet_string (tlv_parser_t tlv, int testmode)
}
return totallen;
}
+
+#endif /* KSBA < 1.9.0 */
diff --git a/common/tlv.h b/common/tlv.h
index cfd615003..af9bc05ad 100644
--- a/common/tlv.h
+++ b/common/tlv.h
@@ -84,8 +84,16 @@ struct tag_info
struct tlv_builder_s;
typedef struct tlv_builder_s *tlv_builder_t;
+
+/* If possible we use the parser functions from libksba along with the
+ * wrappers in tlv-paser.c . */
+#if KSBA_VERSION_NUMBER >= 0x010900 /* 1.9.0 */
+typedef ksba_parser_t tlv_parser_t;
+#else
struct tlv_parser_s;
typedef struct tlv_parser_s *tlv_parser_t;
+#endif
+
/*-- tlv.c --*/