diff options
author | Dariusz Michaluk <d.michaluk@samsung.com> | 2024-02-13 15:38:29 +0100 |
---|---|---|
committer | Dariusz Michaluk <d.michaluk@samsung.com> | 2024-02-13 15:38:29 +0100 |
commit | 031996ef501f8c3d0532f7df1c38cf2e540a4f11 (patch) | |
tree | 27217d793b273edadc969aa3110378aac3c36e9c /lib/coding.c | |
parent | 26bea900a531662c6028ecc06f4adea825658434 (diff) | |
download | libtasn1-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.c | 215 |
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; |