diff options
Diffstat (limited to 'lib/coding.c')
-rw-r--r-- | lib/coding.c | 187 |
1 files changed, 96 insertions, 91 deletions
diff --git a/lib/coding.c b/lib/coding.c index 7141df7..46e67ff 100644 --- a/lib/coding.c +++ b/lib/coding.c @@ -265,6 +265,9 @@ _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); @@ -342,6 +345,9 @@ _asn1_objectid_der (unsigned char *str, unsigned char *der, int *der_len) max_len = *der_len; + if (der == NULL && max_len > 0) + return ASN1_VALUE_NOT_VALID; + temp = malloc (str_len + 2); if (temp == NULL) return ASN1_MEM_ALLOC_ERROR; @@ -473,6 +479,10 @@ _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) { + return ASN1_VALUE_NOT_VALID; + } + is_tag_implicit = 0; if (node->type & CONST_TAG) @@ -830,6 +840,39 @@ error: return err; } +struct vet +{ + unsigned char *ptr; + int size; +}; + +static int setof_compar(const void *_e1, const void *_e2) +{ + unsigned length; + const struct vet *e1 = _e1, *e2 = _e2; + int rval; + + /* The encodings of the component values of a set-of value shall + * appear in ascending order, the encodings being compared + * as octet strings with the shorter components being + * padded at their trailing end with 0-octets. + * The padding octets are for comparison purposes and + * do not appear in the encodings. + */ + length = MIN(e1->size, e2->size); + + rval = memcmp(e1->ptr, e2->ptr, length); + if (rval == 0 && e1->size != e2->size) + { + if (e1->size > e2->size) + rval = 1; + else if (e2->size > e1->size) + rval = -1; + } + + return rval; +} + /******************************************************/ /* Function : _asn1_ordering_set_of */ /* Description: puts the elements of a SET OF type in */ @@ -844,19 +887,19 @@ error: static int _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) { - struct vet - { - int end; - struct vet *next, *prev; - }; - - int counter, len, len2, change; - struct vet *first, *last, *p_vet, *p2_vet; + int counter, len, len2; + struct vet *list = NULL, *tlist; + unsigned list_size = 0; + struct vet *p_vet; asn1_node p; - unsigned char *temp, class; - unsigned long k, length; + unsigned char class; + unsigned i; + 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) @@ -873,33 +916,30 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) if ((p == NULL) || (p->right == NULL)) return ASN1_SUCCESS; - first = last = NULL; while (p) { - p_vet = malloc (sizeof (struct vet)); - if (p_vet == NULL) + list_size++; + 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->next = NULL; - p_vet->prev = last; - if (first == NULL) - first = p_vet; - else - last->next = p_vet; - last = p_vet; + 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); if (err != ASN1_SUCCESS) goto error; counter += len; + p_vet->size += len; len2 = asn1_get_length_der (der + counter, der_len - counter, &len); if (len2 < 0) @@ -908,84 +948,46 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) goto error; } counter += len + len2; + p_vet->size += len + len2; + } else { err = ASN1_DER_ERROR; goto error; } - - p_vet->end = counter; p = p->right; } - p_vet = first; - - while (p_vet) + if (counter > der_len) { - p2_vet = p_vet->next; - counter = 0; - while (p2_vet) - { - length = MIN(p_vet->end - counter, p2_vet->end - p_vet->end); - change = -1; - for (k = 0; k < length; k++) - if (der[counter + k] > der[p_vet->end + k]) - { - change = 1; - break; - } - else if (der[counter + k] < der[p_vet->end + k]) - { - change = 0; - break; - } - - if ((change == -1) - && ((p_vet->end - counter) > (p2_vet->end - p_vet->end))) - change = 1; - - if (change == 1) - { - /* change position */ - temp = malloc (p_vet->end - counter); - if (temp == NULL) - { - err = ASN1_MEM_ALLOC_ERROR; - goto error; - } + err = ASN1_DER_ERROR; + goto error; + } - memcpy (temp, der + counter, (p_vet->end) - counter); - memcpy (der + counter, der + (p_vet->end), - (p2_vet->end) - (p_vet->end)); - memcpy (der + counter + (p2_vet->end) - (p_vet->end), temp, - (p_vet->end) - counter); - free (temp); + qsort(list, list_size, sizeof(struct vet), setof_compar); - p_vet->end = counter + (p2_vet->end - p_vet->end); - } - counter = p_vet->end; + out = malloc(der_len); + if (out == NULL) + { + err = ASN1_MEM_ERROR; + goto error; + } - p2_vet = p2_vet->next; - p_vet = p_vet->next; - } + /* 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); - if (p_vet != first) - p_vet->prev->next = NULL; - else - first = NULL; - free (p_vet); - p_vet = first; - } - return ASN1_SUCCESS; + err = ASN1_SUCCESS; error: - while (first != NULL) - { - p_vet = first; - first = first->next; - free(p_vet); - } + free(list); return err; } @@ -1011,7 +1013,7 @@ error: * length needed. **/ int -asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, +asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len, char *ErrorDescription) { asn1_node node, p, p2; @@ -1037,6 +1039,9 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, max_len = *len; + if (der == NULL && max_len > 0) + return ASN1_VALUE_NOT_VALID; + counter = 0; move = DOWN; p = node; @@ -1057,7 +1062,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, { case ASN1_ETYPE_NULL: max_len--; - if (max_len >= 0) + if (der != NULL && max_len >= 0) der[counter] = 0; counter++; move = RIGHT; @@ -1078,7 +1083,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, goto error; } max_len -= 2; - if (max_len >= 0) + if (der != NULL && max_len >= 0) { der[counter++] = 1; if (p->value[0] == 'F') @@ -1114,7 +1119,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, goto error; } max_len -= len2 + len3; - if (max_len >= 0) + if (der != NULL && max_len >= 0) memcpy (der + counter, p->value, len3 + len2); counter += len3 + len2; } @@ -1186,7 +1191,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, goto error; } max_len -= len2 + len3; - if (max_len >= 0) + if (der != NULL && max_len >= 0) memcpy (der + counter, p->value, len3 + len2); counter += len3 + len2; move = RIGHT; @@ -1228,7 +1233,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, } asn1_length_der (counter - len2, temp, &len3); max_len -= len3; - if (max_len >= 0) + if (der != NULL && max_len >= 0) { memmove (der + len2 + len3, der + len2, counter - len2); memcpy (der + len2, temp, len3); @@ -1269,7 +1274,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, } asn1_length_der (counter - len2, temp, &len3); max_len -= len3; - if (max_len >= 0) + if (der != NULL && max_len >= 0) { memmove (der + len2 + len3, der + len2, counter - len2); memcpy (der + len2, temp, len3); @@ -1292,7 +1297,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, goto error; } max_len -= len2; - if (max_len >= 0) + if (der != NULL && max_len >= 0) memcpy (der + counter, p->value + len3, len2); counter += len2; move = RIGHT; |