[PATCH v2 1/3] unit: Fix memory leak in trust chain test
by Mat Martineau
---
unit/test-key.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/unit/test-key.c b/unit/test-key.c
index 1195da4..455ebb4 100644
--- a/unit/test-key.c
+++ b/unit/test-key.c
@@ -460,8 +460,10 @@ static void test_trust_chain(const void *data)
l_keyring_free(trust);
l_keyring_free(ring);
l_key_free(cakey);
+ l_key_free(intkey);
l_key_free(key);
l_free(cacert);
+ l_free(intcert);
l_free(cert);
}
--
2.10.1
4 years, 5 months
[PATCH 1/5] util: Remove semicolons in single-statement macros
by Mat Martineau
Including semicolons in L_AUTO_CLEANUP_VAR and L_AUTO_FREE_VAR caused
gcc to emit errors related to mixed declarations and code when there
were multiple L_AUTO_* lines or declarations following an L_AUTO_ macro.
---
ell/util.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ell/util.h b/ell/util.h
index 92e7c8a..8d1050e 100644
--- a/ell/util.h
+++ b/ell/util.h
@@ -160,10 +160,10 @@ static inline void l_put_be64(uint64_t val, void *ptr)
}
#define L_AUTO_CLEANUP_VAR(vartype,varname,destroy) \
- vartype varname __attribute__((cleanup(destroy)));
+ vartype varname __attribute__((cleanup(destroy)))
#define L_AUTO_FREE_VAR(vartype,varname) \
- vartype varname __attribute__((cleanup(auto_free)));
+ vartype varname __attribute__((cleanup(auto_free)))
#define L_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
--
2.10.1
4 years, 5 months
[PATCH 1/4] key: Add cert chain validation capability to keyring
by Mat Martineau
Verifying certificate chains was a little awkward using the
L_KEYRING_TRUSTED_ASYM keyring type, which required verifying the
signature and then separately adding the verified certificate to the
"trusted" keyring.
With L_KEYRING_TRUSTED_ASYM_CHAIN, the destination keyring is also
searched for signing keys.
One use model is to have two keyrings:
1. trust_keyring: contains long-lived root and intermediate CA certs.
2. verify_keyring: an L_KEYRING_TRUSTED_ASYM_CHAIN keyring that
is created with "trust_keyring" referenced for
trusted certificates.
In order to validate new certificates, they are added to verify_keyring
in series, starting with certs that are signed by those in
trust_keyring. Once an intermediate CA cert is added to verify_keyring,
certs signed by that intermediate CA can also be added to verify_keyring.
---
ell/key.c | 22 ++++++++++++++++------
ell/key.h | 3 ++-
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/ell/key.c b/ell/key.c
index fc20d29..4cf2307 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -653,15 +653,25 @@ LIB_EXPORT struct l_keyring *l_keyring_new(enum l_keyring_type type,
if (!internal_keyring && !setup_internal_keyring())
return NULL;
- if (type == L_KEYRING_TRUSTED_ASYM) {
- if (!trusted)
- return NULL;
+ switch (type) {
+ case L_KEYRING_SIMPLE:
+ break;
+ case L_KEYRING_TRUSTED_ASYM:
+ case L_KEYRING_TRUSTED_ASYM_CHAIN:
+ {
+ char *option = "";
+
+ if (type == L_KEYRING_TRUSTED_ASYM_CHAIN)
+ option = ":chain";
payload = l_strdup_printf(
- "restrict=asymmetric:key_or_keyring:%d",
- trusted->serial);
+ "restrict=asymmetric:key_or_keyring:%d%s",
+ trusted ? trusted->serial : 0, option);
payload_length = strlen(payload);
- } else if (type != L_KEYRING_SIMPLE) {
+
+ break;
+ }
+ default:
/* Unsupported type */
return NULL;
}
diff --git a/ell/key.h b/ell/key.h
index ff4b543..e7036c6 100644
--- a/ell/key.h
+++ b/ell/key.h
@@ -42,7 +42,8 @@ enum l_key_type {
enum l_keyring_type {
L_KEYRING_SIMPLE = 0,
- L_KEYRING_TRUSTED_ASYM
+ L_KEYRING_TRUSTED_ASYM,
+ L_KEYRING_TRUSTED_ASYM_CHAIN,
};
enum l_key_cipher_type {
--
2.10.1
4 years, 5 months
[PATCH] key: Fix Valgrind warnings
by Mat Martineau
Valgrind doesn't understand all of the keyctl syscalls and how they
set memory, so clear the encrypt/decrypt/sign output buffer to prevent
false positives.
TEST: key crypto
==5884== Conditional jump or move depends on uninitialised value(s)
==5884== at 0x40555F: unpad (key.c:479)
==5884== by 0x4057DF: l_key_decrypt (key.c:556)
==5884== by 0x4021EB: test_key_crypto (test-key.c:535)
==5884== by 0x4039BB: l_test_run (test.c:83)
==5884== by 0x4026F3: main (test-key.c:606)
==5884==
==5884== Conditional jump or move depends on uninitialised value(s)
==5884== at 0x40556F: unpad (key.c:479)
==5884== by 0x4057DF: l_key_decrypt (key.c:556)
==5884== by 0x4021EB: test_key_crypto (test-key.c:535)
==5884== by 0x4039BB: l_test_run (test.c:83)
==5884== by 0x4026F3: main (test-key.c:606)
==5884==
==5884== Conditional jump or move depends on uninitialised value(s)
==5884== at 0x4055AC: unpad (key.c:483)
==5884== by 0x4057DF: l_key_decrypt (key.c:556)
==5884== by 0x4021EB: test_key_crypto (test-key.c:535)
==5884== by 0x4039BB: l_test_run (test.c:83)
==5884== by 0x4026F3: main (test-key.c:606)
==5884==
==5884== Conditional jump or move depends on uninitialised value(s)
==5884== at 0x4C2FC4C: strcmp (vg_replace_strmem.c:842)
==5884== by 0x40223A: test_key_crypto (test-key.c:538)
==5884== by 0x4039BB: l_test_run (test.c:83)
==5884== by 0x4026F3: main (test-key.c:606)
==5884==
==5884== Conditional jump or move depends on uninitialised value(s)
==5884== at 0x4C2FC50: strcmp (vg_replace_strmem.c:842)
==5884== by 0x40223A: test_key_crypto (test-key.c:538)
==5884== by 0x4039BB: l_test_run (test.c:83)
==5884== by 0x4026F3: main (test-key.c:606)
==5884==
==5884== Conditional jump or move depends on uninitialised value(s)
==5884== at 0x4C2FC6C: strcmp (vg_replace_strmem.c:842)
==5884== by 0x40223A: test_key_crypto (test-key.c:538)
==5884== by 0x4039BB: l_test_run (test.c:83)
==5884== by 0x4026F3: main (test-key.c:606)
---
ell/key.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ell/key.c b/ell/key.c
index 0222b39..fc20d29 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -218,6 +218,8 @@ static long kernel_key_eds(int op, int32_t serial, const char *encoding,
.out_len = len_out };
char *info = format_key_info(encoding, hash);
+ memset(out, 0, len_out);
+
result = syscall(__NR_keyctl, op, ¶ms, info ?: "", in, out);
l_free(info);
--
2.10.1
4 years, 6 months
[PATCH] key: Auto-free the signature hash in l_key_verify
by Mat Martineau
This streamlines the existing code by using direct returns rather than a
goto and gets rid of an extra variable. While it does possibly free some
memory immediately after allocation when an invalid checksum type is
requested, this is an uncommon case.
---
ell/key.c | 29 ++++++++++-------------------
1 file changed, 10 insertions(+), 19 deletions(-)
diff --git a/ell/key.c b/ell/key.c
index a71bdc8..0222b39 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -599,14 +599,13 @@ LIB_EXPORT bool l_key_verify(struct l_key *key,
enum l_key_cipher_type kernel_cipher;
ssize_t hash_len;
uint8_t *compare_hash;
- bool success = false;
- uint8_t *sig_hash = l_malloc(len_sig);
+ L_AUTO_FREE_VAR(uint8_t *, sig_hash);
+
+ sig_hash = l_malloc(len_sig);
/* Other checksum types are not yet supported */
- if (checksum != L_CHECKSUM_NONE) {
- success = false;
- goto done;
- }
+ if (checksum != L_CHECKSUM_NONE)
+ return false;
/* The keyctl verify implementation compares the verify results
* before we get a chance to unpad it. Instead, use the *encrypt*
@@ -621,10 +620,8 @@ LIB_EXPORT bool l_key_verify(struct l_key *key,
hash_len = eds_common(key, kernel_cipher, checksum, sig, sig_hash,
len_sig, len_sig, KEYCTL_PKEY_ENCRYPT);
- if (hash_len < 0) {
- success = false;
- goto done;
- }
+ if (hash_len < 0)
+ return false;
compare_hash = sig_hash;
@@ -632,21 +629,15 @@ LIB_EXPORT bool l_key_verify(struct l_key *key,
ssize_t unpad_len;
unpad_len = unpad(sig_hash, NULL, hash_len, 0, 0x01, false);
- if (unpad_len < 0) {
- success = false;
- goto done;
- }
+ if (unpad_len < 0)
+ return false;
compare_hash += hash_len - unpad_len;
hash_len = unpad_len;
}
- success = (len_data == (size_t)hash_len) &&
+ return (len_data == (size_t)hash_len) &&
(memcmp(data, compare_hash, hash_len) == 0);
-done:
- l_free(sig_hash);
-
- return success;
}
LIB_EXPORT struct l_keyring *l_keyring_new(enum l_keyring_type type,
--
2.10.1
4 years, 6 months
[PATCH] key: return proper value and avoid leak
by Thomas Hindoe Paaboel Andersen
The return value was incorrect for bool. The code should also go to
'done' to free sig_hash.
---
ell/key.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/ell/key.c b/ell/key.c
index ad88d81..a71bdc8 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -603,8 +603,10 @@ LIB_EXPORT bool l_key_verify(struct l_key *key,
uint8_t *sig_hash = l_malloc(len_sig);
/* Other checksum types are not yet supported */
- if (checksum != L_CHECKSUM_NONE)
- return -EINVAL;
+ if (checksum != L_CHECKSUM_NONE) {
+ success = false;
+ goto done;
+ }
/* The keyctl verify implementation compares the verify results
* before we get a chance to unpad it. Instead, use the *encrypt*
--
2.9.3
4 years, 6 months
[PATCH] genl: Add l_genl_msg_append_attrv
by Andrew Zaborowski
Try to minimise the amount of buffers allocated and copied by clients
when building a message attribute that is a concatenation of other
buffers, such as an IE sequence.
---
ell/genl.c | 32 ++++++++++++++++++++++++++++++++
ell/genl.h | 2 ++
2 files changed, 34 insertions(+)
diff --git a/ell/genl.c b/ell/genl.c
index 85e447a..c522ae7 100644
--- a/ell/genl.c
+++ b/ell/genl.c
@@ -793,6 +793,38 @@ LIB_EXPORT bool l_genl_msg_append_attr(struct l_genl_msg *msg, uint16_t type,
return true;
}
+LIB_EXPORT bool l_genl_msg_append_attrv(struct l_genl_msg *msg, uint16_t type,
+ struct iovec *iov, size_t iov_len)
+{
+ struct nlattr *nla;
+ size_t len = 0;
+ unsigned int i;
+
+ if (unlikely(!msg))
+ return false;
+
+ for (i = 0; i < iov_len; i++)
+ len += iov[i].iov_len;
+
+ if (msg->len + NLA_HDRLEN + NLA_ALIGN(len) > msg->size)
+ return false;
+
+ nla = msg->data + msg->len;
+ nla->nla_len = NLA_HDRLEN + len;
+ nla->nla_type = type;
+
+ msg->len += NLA_HDRLEN;
+
+ for (i = 0; i < iov_len; i++, iov++) {
+ memcpy(msg->data + msg->len, iov->iov_base, iov->iov_len);
+ msg->len += iov->iov_len;
+ }
+
+ msg->len += NLA_ALIGN(len) - len;
+
+ return true;
+}
+
LIB_EXPORT bool l_genl_msg_enter_nested(struct l_genl_msg *msg, uint16_t type)
{
struct nlattr *nla;
diff --git a/ell/genl.h b/ell/genl.h
index 5b37d55..fe188d9 100644
--- a/ell/genl.h
+++ b/ell/genl.h
@@ -71,6 +71,8 @@ int l_genl_msg_get_error(struct l_genl_msg *msg);
bool l_genl_msg_append_attr(struct l_genl_msg *msg, uint16_t type,
uint16_t len, const void *data);
+bool l_genl_msg_append_attrv(struct l_genl_msg *msg, uint16_t type,
+ struct iovec *iov, size_t iov_len);
bool l_genl_msg_enter_nested(struct l_genl_msg *msg, uint16_t type);
bool l_genl_msg_leave_nested(struct l_genl_msg *msg);
--
2.7.4
4 years, 6 months
ELL API changes before stabilizing
by Mat Martineau
We will soon reach a point where breaking changes to the ELL APIs will get
a lot more painful - changes already create a headache for the handful of
projects we know about. Given that, I took a look over the public headers
to see if there were any obvious adjustments to be made, and only found a
few issues that jumped out at me.
1. timeout: extra nanosecond APIs with extremely_long_function_names. We
could scrap the *_with_nanosecond calls and include nanoseconds in
l_timeout_create and l_timeout_modify.
2. timeout: Why not use time_t for seconds? Yeah, 4 billion seconds should
be enough for anyone, but the same argument could be made for the
underlying struct timespec that's used for the system calls.
3. main: We recently changed l_main_exit() to be a cleanup function. It
used to trigger an exit action. It would be more consistent to name the
function for what it does rather than when it should be run
(l_main_cleanup()?).
4. uintset: Why does uintset_new() create a set with min == 1? C
programmers are more likely to assume it's 0-indexed. Maybe we don't need
both l_uintset_new and l_uintset_new_from_range. One function that takes
min and max seems sufficient.
Anything else you've noticed?
--
Mat Martineau
Intel OTC
4 years, 6 months
[PATCH] genl: Add l_genl_msg_attr_append_data
by Andrew Zaborowski
Try to minimise the amount of buffers allocated and copied by clients
when building a message attribute that is a concatenation of other
buffers, such as an IE sequence. The client would the following three
calls:
l_genl_msg_enter_nested
l_genl_msg_attr_append_data
l_genl_msg_leave_nested
---
ell/genl.c | 26 ++++++++++++++++++++++++++
ell/genl.h | 1 +
2 files changed, 27 insertions(+)
diff --git a/ell/genl.c b/ell/genl.c
index 85e447a..aefea5f 100644
--- a/ell/genl.c
+++ b/ell/genl.c
@@ -828,14 +828,40 @@ LIB_EXPORT bool l_genl_msg_leave_nested(struct l_genl_msg *msg)
if (unlikely(msg->nesting_level == 0))
return false;
+ if (NLA_ALIGN(msg->len) > msg->size)
+ return false;
+
nla = msg->nests[msg->nesting_level - 1];
nla->nla_len = msg->len - nla->nla_len;
msg->nesting_level -= 1;
+ msg->len = NLA_ALIGN(msg->len);
+
return true;
}
+LIB_EXPORT void *l_genl_msg_attr_append_data(struct l_genl_msg *msg,
+ uint16_t len)
+{
+ void *ptr;
+
+ if (unlikely(!msg))
+ return false;
+
+ if (msg->len + len > msg->size)
+ return false;
+
+ if (unlikely(msg->nesting_level == 0))
+ return false;
+
+ ptr = msg->data + msg->len;
+
+ msg->len += len;
+
+ return ptr;
+}
+
#define NLA_OK(nla,len) ((len) >= (int) sizeof(struct nlattr) && \
(nla)->nla_len >= sizeof(struct nlattr) && \
(nla)->nla_len <= (len))
diff --git a/ell/genl.h b/ell/genl.h
index 5b37d55..5bfa459 100644
--- a/ell/genl.h
+++ b/ell/genl.h
@@ -73,6 +73,7 @@ bool l_genl_msg_append_attr(struct l_genl_msg *msg, uint16_t type,
uint16_t len, const void *data);
bool l_genl_msg_enter_nested(struct l_genl_msg *msg, uint16_t type);
bool l_genl_msg_leave_nested(struct l_genl_msg *msg);
+void *l_genl_msg_attr_append_data(struct l_genl_msg *msg, uint16_t len);
bool l_genl_attr_init(struct l_genl_attr *attr, struct l_genl_msg *msg);
bool l_genl_attr_next(struct l_genl_attr *attr, uint16_t *type,
--
2.7.4
4 years, 6 months
[PATCH 1/2] tls: Move DER code to the TLS module and make static
by Mat Martineau
---
ell/cipher-private.h | 37 ------------------------------
ell/cipher.c | 50 -----------------------------------------
ell/tls.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 62 insertions(+), 88 deletions(-)
delete mode 100644 ell/cipher-private.h
diff --git a/ell/cipher-private.h b/ell/cipher-private.h
deleted file mode 100644
index 77ddd06..0000000
--- a/ell/cipher-private.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *
- * Embedded Linux library
- *
- * Copyright (C) 2015 Intel Corporation. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#define ASN1_ID(class, pc, tag) (((class) << 6) | ((pc) << 5) | (tag))
-
-#define ASN1_CLASS_UNIVERSAL 0
-
-#define ASN1_ID_SEQUENCE ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x10)
-#define ASN1_ID_SET ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x11)
-#define ASN1_ID_INTEGER ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x02)
-#define ASN1_ID_BIT_STRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x03)
-#define ASN1_ID_OCTET_STRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x04)
-#define ASN1_ID_OID ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x06)
-#define ASN1_ID_UTF8STRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x0c)
-#define ASN1_ID_PRINTABLESTRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x13)
-
-uint8_t *der_find_elem(uint8_t *buf, size_t len_in, int index,
- uint8_t *tag, size_t *len_out);
diff --git a/ell/cipher.c b/ell/cipher.c
index 0af0b4b..8312451 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -31,7 +31,6 @@
#include "util.h"
#include "cipher.h"
-#include "cipher-private.h"
#include "private.h"
#include "random.h"
@@ -292,52 +291,3 @@ LIB_EXPORT bool l_cipher_set_iv(struct l_cipher *cipher, const uint8_t *iv,
return true;
}
-
-static inline int parse_asn1_definite_length(const uint8_t **buf,
- size_t *len)
-{
- int n;
- size_t result = 0;
-
- (*len)--;
-
- if (!(**buf & 0x80))
- return *(*buf)++;
-
- n = *(*buf)++ & 0x7f;
- if ((size_t) n > *len)
- return -1;
-
- *len -= n;
- while (n--)
- result = (result << 8) | *(*buf)++;
-
- return result;
-}
-
-/* Return index'th element in a DER SEQUENCE */
-uint8_t *der_find_elem(uint8_t *buf, size_t len_in, int index,
- uint8_t *tag, size_t *len_out)
-{
- int tlv_len;
-
- while (1) {
- if (len_in < 2)
- return NULL;
-
- *tag = *buf++;
- len_in--;
-
- tlv_len = parse_asn1_definite_length((void *) &buf, &len_in);
- if (tlv_len < 0 || (size_t) tlv_len > len_in)
- return NULL;
-
- if (index-- == 0) {
- *len_out = tlv_len;
- return buf;
- }
-
- buf += tlv_len;
- len_in -= tlv_len;
- }
-}
diff --git a/ell/tls.c b/ell/tls.c
index 9b33ffb..bc4c210 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -35,7 +35,6 @@
#include "random.h"
#include "pem.h"
#include "tls-private.h"
-#include "cipher-private.h"
#include "key.h"
void tls10_prf(const uint8_t *secret, size_t secret_len,
@@ -2310,6 +2309,19 @@ LIB_EXPORT const char *l_tls_alert_to_str(enum l_tls_alert_desc desc)
/* X509 Certificates and Certificate Chains */
+#define ASN1_ID(class, pc, tag) (((class) << 6) | ((pc) << 5) | (tag))
+
+#define ASN1_CLASS_UNIVERSAL 0
+
+#define ASN1_ID_SEQUENCE ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x10)
+#define ASN1_ID_SET ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x11)
+#define ASN1_ID_INTEGER ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x02)
+#define ASN1_ID_BIT_STRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x03)
+#define ASN1_ID_OCTET_STRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x04)
+#define ASN1_ID_OID ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x06)
+#define ASN1_ID_UTF8STRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x0c)
+#define ASN1_ID_PRINTABLESTRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x13)
+
#define X509_CERTIFICATE_POS 0
#define X509_TBSCERTIFICATE_POS 0
#define X509_TBSCERT_VERSION_POS 0
@@ -2329,6 +2341,55 @@ LIB_EXPORT const char *l_tls_alert_to_str(enum l_tls_alert_desc desc)
#define X509_SIGNATURE_ALGORITHM_POS 1
#define X509_SIGNATURE_VALUE_POS 2
+static inline int parse_asn1_definite_length(const uint8_t **buf,
+ size_t *len)
+{
+ int n;
+ size_t result = 0;
+
+ (*len)--;
+
+ if (!(**buf & 0x80))
+ return *(*buf)++;
+
+ n = *(*buf)++ & 0x7f;
+ if ((size_t) n > *len)
+ return -1;
+
+ *len -= n;
+ while (n--)
+ result = (result << 8) | *(*buf)++;
+
+ return result;
+}
+
+/* Return index'th element in a DER SEQUENCE */
+static uint8_t *der_find_elem(uint8_t *buf, size_t len_in, int index,
+ uint8_t *tag, size_t *len_out)
+{
+ int tlv_len;
+
+ while (1) {
+ if (len_in < 2)
+ return NULL;
+
+ *tag = *buf++;
+ len_in--;
+
+ tlv_len = parse_asn1_definite_length((void *) &buf, &len_in);
+ if (tlv_len < 0 || (size_t) tlv_len > len_in)
+ return NULL;
+
+ if (index-- == 0) {
+ *len_out = tlv_len;
+ return buf;
+ }
+
+ buf += tlv_len;
+ len_in -= tlv_len;
+ }
+}
+
/* Return an element in a DER SEQUENCE structure by path */
static inline uint8_t *der_find_elem_by_path(uint8_t *buf, size_t len_in,
uint8_t tag, size_t *len_out,
--
2.10.1
4 years, 6 months