summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-08-29 16:34:39 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-08-29 17:23:39 +0200
commit564ca04592ad5604fe5c7344ec9e62bc04879ef7 (patch)
treef5a21bd1fbf550c556f7f71ca2f2611ec05566b2
parent0d3ab4992fcc0798c48b686b9abc68d058feb2b9 (diff)
downloadlibtasn1-564ca04592ad5604fe5c7344ec9e62bc04879ef7.tar.gz
perform sanity checks in Time field
-rw-r--r--lib/decoding.c55
1 files changed, 51 insertions, 4 deletions
diff --git a/lib/decoding.c b/lib/decoding.c
index fd6ef5b..9622fda 100644
--- a/lib/decoding.c
+++ b/lib/decoding.c
@@ -276,12 +276,17 @@ asn1_get_octet_der (const unsigned char *der, int der_len,
}
/* Returns ASN1_SUCCESS on success or an error code on error.
+ * type should be one of ASN1_ETYPE_GENERALIZED_TIME or ASN1_ETYPE_UTC_TIME.
*/
static int
-_asn1_get_time_der (const unsigned char *der, int der_len, int *ret_len,
- char *str, int str_size)
+_asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, int *ret_len,
+ char *str, int str_size, unsigned flags)
{
int len_len, str_len;
+ unsigned i;
+ unsigned sign_count = 0;
+ unsigned dot_count = 0;
+ const unsigned char *p;
if (der_len <= 0 || str == NULL)
return ASN1_DER_ERROR;
@@ -290,6 +295,48 @@ _asn1_get_time_der (const unsigned char *der, int der_len, int *ret_len,
if (str_len <= 0 || str_size < str_len)
return ASN1_DER_ERROR;
+ /* perform some sanity checks on the data */
+ if (str_len < 8)
+ {
+ warn();
+ return ASN1_DER_ERROR;
+ }
+
+ p = &der[len_len];
+ for (i=0;i<str_len-1;i++)
+ {
+ if (isdigit(p[i]) == 0)
+ {
+ if (type == ASN1_ETYPE_GENERALIZED_TIME)
+ {
+ /* tolerate lax encodings */
+ if (p[i] == '.' && dot_count == 0)
+ {
+ dot_count++;
+ continue;
+ }
+
+ /* This is not really valid DER, but there are
+ * structures using that */
+ if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) &&
+ (p[i] == '+' || p[i] == '-') && sign_count == 0)
+ {
+ sign_count++;
+ continue;
+ }
+ }
+
+ warn();
+ return ASN1_DER_ERROR;
+ }
+ }
+
+ if (sign_count == 0 && p[str_len-1] != 'Z')
+ {
+ warn();
+ return ASN1_DER_ERROR;
+ }
+
memcpy (str, der + len_len, str_len);
str[str_len] = 0;
*ret_len = str_len + len_len;
@@ -1181,8 +1228,8 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len,
case ASN1_ETYPE_GENERALIZED_TIME:
case ASN1_ETYPE_UTC_TIME:
result =
- _asn1_get_time_der (der + counter, ider_len, &len2, temp,
- sizeof (temp) - 1);
+ _asn1_get_time_der (type_field (p->type), der + counter, ider_len, &len2, temp,
+ sizeof (temp) - 1, flags);
if (result != ASN1_SUCCESS)
{
warn();