summaryrefslogtreecommitdiff
path: root/lib/coding.c
diff options
context:
space:
mode:
authorDariusz Michaluk <d.michaluk@samsung.com>2024-02-13 15:38:29 +0100
committerDariusz Michaluk <d.michaluk@samsung.com>2024-02-13 15:38:29 +0100
commit031996ef501f8c3d0532f7df1c38cf2e540a4f11 (patch)
tree27217d793b273edadc969aa3110378aac3c36e9c /lib/coding.c
parent26bea900a531662c6028ecc06f4adea825658434 (diff)
downloadlibtasn1-031996ef501f8c3d0532f7df1c38cf2e540a4f11.tar.gz
libtasn1-031996ef501f8c3d0532f7df1c38cf2e540a4f11.tar.bz2
libtasn1-031996ef501f8c3d0532f7df1c38cf2e540a4f11.zip
Imported Upstream version 4.19.0upstream/4.19.0upstream
Diffstat (limited to 'lib/coding.c')
-rw-r--r--lib/coding.c215
1 files changed, 144 insertions, 71 deletions
diff --git a/lib/coding.c b/lib/coding.c
index 46e67ff..ea5bc37 100644
--- a/lib/coding.c
+++ b/lib/coding.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2014 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2022 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -121,7 +121,7 @@ asn1_length_der (unsigned long int len, unsigned char *der, int *der_len)
/******************************************************/
static void
_asn1_tag_der (unsigned char class, unsigned int tag_value,
- unsigned char *ans, int *ans_len)
+ unsigned char ans[ASN1_MAX_TAG_SIZE], int *ans_len)
{
int k;
unsigned char temp[ASN1_MAX_TAG_SIZE];
@@ -265,9 +265,6 @@ _asn1_time_der (unsigned char *str, int str_len, unsigned char *der,
int len_len;
int max_len;
- if (der == NULL)
- return ASN1_VALUE_NOT_VALID;
-
max_len = *der_len;
asn1_length_der (str_len, (max_len > 0) ? der : NULL, &len_len);
@@ -295,7 +292,8 @@ _asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str)
if (str_len<0) return;
memcpy(temp,der+len_len,str_len);
*der_len=str_len+len_len;
- switch(str_len){
+ switch(str_len)
+ {
case 11:
temp[10]=0;
strcat(temp,"00+0000");
@@ -319,8 +317,30 @@ _asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str)
}
*/
+static void
+encode_val (uint64_t val, unsigned char *der, int max_len, int *der_len)
+{
+ int first, k;
+ unsigned char bit7;
+
+ first = 0;
+ for (k = sizeof (val); k >= 0; k--)
+ {
+ bit7 = (val >> (k * 7)) & 0x7F;
+ if (bit7 || first || !k)
+ {
+ if (k)
+ bit7 |= 0x80;
+ if (max_len > (*der_len))
+ der[*der_len] = bit7;
+ (*der_len)++;
+ first = 1;
+ }
+ }
+}
+
/******************************************************/
-/* Function : _asn1_objectid_der */
+/* Function : _asn1_object_id_der */
/* Description: creates the DER coding for an */
/* OBJECT IDENTIFIER type (length included). */
/* Parameters: */
@@ -335,15 +355,15 @@ _asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str)
/* or an error value. */
/******************************************************/
static int
-_asn1_objectid_der (unsigned char *str, unsigned char *der, int *der_len)
+_asn1_object_id_der (const char *str, unsigned char *der, int *der_len)
{
- int len_len, counter, k, first, max_len;
+ int len_len, counter, max_len;
char *temp, *n_end, *n_start;
- unsigned char bit7;
uint64_t val, val1 = 0;
int str_len = _asn1_strlen (str);
max_len = *der_len;
+ *der_len = 0;
if (der == NULL && max_len > 0)
return ASN1_VALUE_NOT_VALID;
@@ -365,30 +385,30 @@ _asn1_objectid_der (unsigned char *str, unsigned char *der, int *der_len)
counter++;
if (counter == 1)
- val1 = val;
- else if (counter == 2)
{
- if (max_len > 0)
- der[0] = 40 * val1 + val;
- *der_len = 1;
+ val1 = val;
}
- else
+ else if (counter == 2)
{
- first = 0;
- for (k = sizeof(val); k >= 0; k--)
+ uint64_t val0;
+
+ if (val1 > 2)
{
- bit7 = (val >> (k * 7)) & 0x7F;
- if (bit7 || first || !k)
- {
- if (k)
- bit7 |= 0x80;
- if (max_len > (*der_len))
- der[*der_len] = bit7;
- (*der_len)++;
- first = 1;
- }
+ free (temp);
+ return ASN1_VALUE_NOT_VALID;
+ }
+ else if ((val1 == 0 || val1 == 1) && val > 39)
+ {
+ free (temp);
+ return ASN1_VALUE_NOT_VALID;
}
+ val0 = 40 * val1 + val;
+ encode_val (val0, der, max_len, der_len);
+ }
+ else
+ {
+ encode_val (val, der, max_len, der_len);
}
n_start = n_end + 1;
}
@@ -409,6 +429,48 @@ _asn1_objectid_der (unsigned char *str, unsigned char *der, int *der_len)
return ASN1_SUCCESS;
}
+/**
+ * asn1_object_id_der:
+ * @str: An object identifier in numeric, dot format.
+ * @der: buffer to hold the returned encoding (may be %NULL).
+ * @der_len: initially the size of @der; will hold the final size.
+ * @flags: must be zero
+ *
+ * Creates the DER encoding of the provided object identifier.
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding was OK, %ASN1_VALUE_NOT_VALID
+ * if @str is not a valid OID, %ASN1_MEM_ERROR if the @der
+ * vector isn't big enough and in this case @der_len will contain the
+ * length needed.
+ **/
+int
+asn1_object_id_der (const char *str, unsigned char *der, int *der_len,
+ unsigned flags)
+{
+ unsigned char tag_der[MAX_TAG_LEN];
+ int tag_len = 0, r;
+ int max_len = *der_len;
+
+ *der_len = 0;
+
+ _asn1_tag_der (ETYPE_CLASS (ASN1_ETYPE_OBJECT_ID),
+ ETYPE_TAG (ASN1_ETYPE_OBJECT_ID), tag_der, &tag_len);
+
+ if (max_len > tag_len)
+ {
+ memcpy (der, tag_der, tag_len);
+ }
+ max_len -= tag_len;
+ der += tag_len;
+
+ r = _asn1_object_id_der (str, der, &max_len);
+ if (r == ASN1_MEM_ERROR || r == ASN1_SUCCESS)
+ {
+ *der_len = max_len + tag_len;
+ }
+
+ return r;
+}
static const unsigned char bit_mask[] =
{ 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
@@ -479,9 +541,8 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der,
int is_tag_implicit, len2, len3;
unsigned char temp[SIZEOF_UNSIGNED_INT];
- if (der == NULL && *max_len > 0) {
+ if (der == NULL && *max_len > 0)
return ASN1_VALUE_NOT_VALID;
- }
is_tag_implicit = 0;
@@ -489,7 +550,7 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der,
{
p = node->down;
if (p == NULL)
- return ASN1_DER_ERROR;
+ return ASN1_DER_ERROR;
/* When there are nested tags we must complete them reverse to
the order they were created. This is because completing a tag
modifies all data within it, including the incomplete tags
@@ -607,7 +668,8 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter,
{
asn1_node p;
int tag_len, is_tag_implicit;
- unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)];
+ unsigned char class, class_implicit =
+ 0, temp[MAX (SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)];
unsigned long tag_implicit = 0;
unsigned char tag_der[MAX_TAG_LEN];
@@ -737,7 +799,7 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node)
p = node->down;
while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) ||
- (type_field (p->type) == ASN1_ETYPE_SIZE)))
+ (type_field (p->type) == ASN1_ETYPE_SIZE)))
p = p->right;
if ((p == NULL) || (p->right == NULL))
@@ -748,7 +810,7 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node)
{
p_vet = malloc (sizeof (struct vet));
if (p_vet == NULL)
- {
+ {
err = ASN1_MEM_ALLOC_ERROR;
goto error;
}
@@ -767,7 +829,7 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node)
if (err != ASN1_SUCCESS)
goto error;
- t = ((unsigned int)class) << 24;
+ t = ((unsigned int) class) << 24;
p_vet->value = t | tag;
counter += len2;
@@ -835,7 +897,7 @@ error:
{
p_vet = first;
first = first->next;
- free(p_vet);
+ free (p_vet);
}
return err;
}
@@ -846,7 +908,8 @@ struct vet
int size;
};
-static int setof_compar(const void *_e1, const void *_e2)
+static int
+setof_compar (const void *_e1, const void *_e2)
{
unsigned length;
const struct vet *e1 = _e1, *e2 = _e2;
@@ -859,15 +922,15 @@ static int setof_compar(const void *_e1, const void *_e2)
* The padding octets are for comparison purposes and
* do not appear in the encodings.
*/
- length = MIN(e1->size, e2->size);
+ length = MIN (e1->size, e2->size);
- rval = memcmp(e1->ptr, e2->ptr, length);
+ rval = memcmp (e1->ptr, e2->ptr, length);
if (rval == 0 && e1->size != e2->size)
{
if (e1->size > e2->size)
- rval = 1;
+ rval = 1;
else if (e2->size > e1->size)
- rval = -1;
+ rval = -1;
}
return rval;
@@ -897,9 +960,6 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
unsigned char *out = NULL;
int err;
- if (der == NULL)
- return ASN1_VALUE_NOT_VALID;
-
counter = 0;
if (type_field (node->type) != ASN1_ETYPE_SET_OF)
@@ -907,7 +967,7 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
p = node->down;
while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) ||
- (type_field (p->type) == ASN1_ETYPE_SIZE)))
+ (type_field (p->type) == ASN1_ETYPE_SIZE)))
p = p->right;
if (p == NULL)
return ASN1_VALUE_NOT_VALID;
@@ -919,27 +979,27 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
while (p)
{
list_size++;
- tlist = realloc (list, list_size*sizeof(struct vet));
+ tlist = realloc (list, list_size * sizeof (struct vet));
if (tlist == NULL)
{
err = ASN1_MEM_ALLOC_ERROR;
goto error;
}
list = tlist;
- p_vet = &list[list_size-1];
+ p_vet = &list[list_size - 1];
- p_vet->ptr = der+counter;
+ p_vet->ptr = der + counter;
p_vet->size = 0;
/* extraction of tag and length */
if (der_len - counter > 0)
{
err = asn1_get_tag_der (der + counter, der_len - counter, &class,
- &len, NULL);
+ &len, NULL);
if (err != ASN1_SUCCESS)
goto error;
counter += len;
- p_vet->size += len;
+ p_vet->size += len;
len2 = asn1_get_length_der (der + counter, der_len - counter, &len);
if (len2 < 0)
@@ -948,7 +1008,7 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
goto error;
}
counter += len + len2;
- p_vet->size += len + len2;
+ p_vet->size += len + len2;
}
else
@@ -965,9 +1025,9 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
goto error;
}
- qsort(list, list_size, sizeof(struct vet), setof_compar);
+ qsort (list, list_size, sizeof (struct vet), setof_compar);
- out = malloc(der_len);
+ out = malloc (der_len);
if (out == NULL)
{
err = ASN1_MEM_ERROR;
@@ -976,18 +1036,19 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
/* the sum of p_vet->size == der_len */
counter = 0;
- for (i=0;i<list_size;i++) {
- p_vet = &list[i];
- memcpy(out+counter, p_vet->ptr, p_vet->size);
- counter += p_vet->size;
- }
- memcpy(der, out, der_len);
- free(out);
+ for (i = 0; i < list_size; i++)
+ {
+ p_vet = &list[i];
+ memcpy (out + counter, p_vet->ptr, p_vet->size);
+ counter += p_vet->size;
+ }
+ memcpy (der, out, der_len);
+ free (out);
err = ASN1_SUCCESS;
error:
- free(list);
+ free (list);
return err;
}
@@ -1013,14 +1074,15 @@ error:
* length needed.
**/
int
-asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len,
- char *ErrorDescription)
+asn1_der_coding (asn1_node_const element, const char *name, void *ider,
+ int *len, char *ErrorDescription)
{
asn1_node node, p, p2;
- unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)];
+ unsigned char temp[MAX (LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)];
int counter, counter_old, len2, len3, move, max_len, max_len_old;
int err;
unsigned char *der = ider;
+ unsigned char dummy;
if (ErrorDescription)
ErrorDescription[0] = 0;
@@ -1040,7 +1102,10 @@ asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len
max_len = *len;
if (der == NULL && max_len > 0)
- return ASN1_VALUE_NOT_VALID;
+ {
+ err = ASN1_VALUE_NOT_VALID;
+ goto error;
+ }
counter = 0;
move = DOWN;
@@ -1053,7 +1118,7 @@ asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len
max_len_old = max_len;
if (move != UP)
{
- p->start = counter;
+ p->start = counter;
err = _asn1_insert_tag_der (p, der, &counter, &max_len);
if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
goto error;
@@ -1141,7 +1206,9 @@ asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len
goto error;
}
len2 = max_len;
- err = _asn1_objectid_der (p->value, der + counter, &len2);
+ err =
+ _asn1_object_id_der ((char *) p->value,
+ der ? der + counter : &dummy, &len2);
if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
goto error;
@@ -1159,7 +1226,9 @@ asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len
goto error;
}
len2 = max_len;
- err = _asn1_time_der (p->value, p->value_len, der + counter, &len2);
+ err =
+ _asn1_time_der (p->value, p->value_len,
+ der ? der + counter : &dummy, &len2);
if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
goto error;
@@ -1227,7 +1296,9 @@ asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len
p->tmp_ival = 0;
if ((type_field (p->type) == ASN1_ETYPE_SET) && (max_len >= 0))
{
- err = _asn1_ordering_set (der + len2, counter - len2, p);
+ err =
+ _asn1_ordering_set (der ? der + len2 : &dummy,
+ counter - len2, p);
if (err != ASN1_SUCCESS)
goto error;
}
@@ -1268,7 +1339,9 @@ asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len
if ((type_field (p->type) == ASN1_ETYPE_SET_OF)
&& (counter - len2 > 0) && (max_len >= 0))
{
- err = _asn1_ordering_set_of (der + len2, counter - len2, p);
+ err =
+ _asn1_ordering_set_of (der ? der + len2 : &dummy,
+ counter - len2, p);
if (err != ASN1_SUCCESS)
goto error;
}
@@ -1309,7 +1382,7 @@ asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len
if ((move != DOWN) && (counter != counter_old))
{
- p->end = counter - 1;
+ p->end = counter - 1;
err = _asn1_complete_explicit_tag (p, der, &counter, &max_len);
if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
goto error;