/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */ /* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */ #include "precomp.h" #if defined(ENABLE_COMPARE) || defined(ENABLE_BER) /* compare two object identifiers; return 0 iff equal */ int ASN1objectidentifier_cmp(ASN1objectidentifier_t *v1, ASN1objectidentifier_t *v2) { ASN1uint32_t l, l1, l2, i; ASN1objectidentifier_t p1 = *v1; ASN1objectidentifier_t p2 = *v2; l1 = GetObjectIdentifierCount(p1); l2 = GetObjectIdentifierCount(p2); l = (l1 > l2) ? l2 : l1; // min(l1,l2) for (i = 0; i < l; i++) { if (p1->value != p2->value) return p1->value - p2->value; p1 = p1->next; p2 = p2->next; } return l1 - l2; } int ASN1objectidentifier2_cmp(ASN1objectidentifier2_t *v1, ASN1objectidentifier2_t *v2) { ASN1uint16_t len, i; len = (v1->count > v2->count) ? v2->count : v1->count; // min(l1,l2) for (i = 0; i < len; i++) { if (v1->value[i] != v2->value[i]) { return ((int) v1->value[i] - (int) v2->value[i]); } } return ((int) v1->count - (int) v2->count); } static const ASN1uint8_t c_aBitMask2[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe }; /* compare two bit strings; return 0 iff equal */ int ASN1bitstring_cmp(ASN1bitstring_t *v1, ASN1bitstring_t *v2, int ignorezero) { ASN1uint32_t l, l1, l2; ASN1octet_t o1, o2; int ret; l1 = v1->length; l2 = v2->length; l = l1; if (l > l2) l = l2; if (ignorezero) { if (l1 > l) ASN1PEREncRemoveZeroBits(&l1, v1->value, l); if (l2 > l) ASN1PEREncRemoveZeroBits(&l2, v2->value, l); } if (l > 7) { ret = memcmp(v1->value, v2->value, l / 8); if (ret) return ret; } if (l & 7) { o1 = v1->value[l / 8] & c_aBitMask2[l & 7]; o2 = v2->value[l / 8] & c_aBitMask2[l & 7]; ret = o1 - o2; if (ret) return ret; } return l1 - l2; } /* compare two octet strings; return 0 iff equal */ int ASN1octetstring_cmp(ASN1octetstring_t *v1, ASN1octetstring_t *v2) { ASN1uint32_t l, l1, l2; int ret; l1 = v1->length; l2 = v2->length; l = l1; if (l > l2) l = l2; if (l) { ret = memcmp(v1->value, v2->value, l); if (ret) return ret; } return l1 - l2; } #ifdef ENABLE_EXTERNAL /* compare two external; return 0 iff equal */ int ASN1external_cmp(ASN1external_t *v1, ASN1external_t *v2) { int ret; if ((ret = (v1->identification.o - v2->identification.o))) return ret; switch (v1->identification.o) { case ASN1external_identification_syntax_o: if ((ret = ASN1objectidentifier_cmp(&v1->identification.u.syntax, &v2->identification.u.syntax))) return ret; break; case ASN1external_identification_presentation_context_id_o: if ((ret = (v1->identification.u.presentation_context_id - v2->identification.u.presentation_context_id))) return ret; break; case ASN1external_identification_context_negotiation_o: if ((ret = ( v1->identification.u.context_negotiation.presentation_context_id - v2->identification.u.context_negotiation.presentation_context_id))) return ret; if ((ret = ASN1objectidentifier_cmp( &v1->identification.u.context_negotiation.transfer_syntax, &v2->identification.u.context_negotiation.transfer_syntax))) return ret; break; } if (ASN1BITTEST(v1->o, ASN1external_data_value_descriptor_o)) { if (ASN1BITTEST(v2->o, ASN1external_data_value_descriptor_o)) { if ((ret = ASN1ztcharstring_cmp( v1->data_value_descriptor, v2->data_value_descriptor))) return ret; } else { return 1; } } else { return 1; } if ((ret = (v1->data_value.o - v2->data_value.o))) return ret; switch (v1->data_value.o) { case ASN1external_data_value_notation_o: if ((ret = ASN1open_cmp(&v1->data_value.u.notation, &v2->data_value.u.notation))) return ret; break; case ASN1external_data_value_encoded_o: if ((ret = ASN1bitstring_cmp(&v1->data_value.u.encoded, &v2->data_value.u.encoded, 0))) return ret; break; } return 0; } #endif // ENABLE_EXTERNAL #ifdef ENABLE_REAL /* compare two reals; return 0 iff equal */ int ASN1real_cmp(ASN1real_t *v1, ASN1real_t *v2) { ASN1intx_t e, e1, e2, m1, m2, h; int ret = 0; ZeroMemory(&e1, sizeof(e1)); ZeroMemory(&e2, sizeof(e2)); ZeroMemory(&m1, sizeof(m1)); ZeroMemory(&m2, sizeof(m2)); if (v1->type == eReal_PlusInfinity || v2->type == eReal_MinusInfinity) return 1; if (v2->type == eReal_PlusInfinity || v1->type == eReal_MinusInfinity) return -1; if (v1->type != eReal_Normal || v2->type != eReal_Normal) return 0; switch (v1->base) { case 2: if (! ASN1intx_dup(&e1, &v1->exponent)) { ret = -1; goto MyExit; } break; case 8: ASN1intx_muloctet(&e1, &v1->exponent, 3); break; case 16: ASN1intx_muloctet(&e1, &v1->exponent, 4); break; } switch (v2->base) { case 2: if (! ASN1intx_dup(&e2, &v2->exponent)) { ret = 1; goto MyExit; } break; case 8: ASN1intx_muloctet(&e2, &v2->exponent, 3); break; case 16: ASN1intx_muloctet(&e2, &v2->exponent, 4); break; } if (! ASN1intx_dup(&m1, &v1->mantissa)) { ret = -1; goto MyExit; } if (! ASN1intx_dup(&m2, &v2->mantissa)) { ret = 1; goto MyExit; } ASN1intx_sub(&e, &e1, &e2); for (;;) { ret = ASN1intx_cmp(&e, &ASN1intx_0); if (!ret) break; if (ret > 0) { ASN1intx_muloctet(&h, &m1, 2); ASN1intx_free(&m1); m1 = h; ASN1intx_dec(&e); } else { ASN1intx_muloctet(&h, &m2, 2); ASN1intx_free(&m2); m2 = h; ASN1intx_inc(&e); } } // lonchanc: what happened to the memory allocated for e, // should we call ASN1intx_free(&e)? ret = ASN1intx_cmp(&m1, &m2); MyExit: ASN1intx_free(&m1); ASN1intx_free(&m2); ASN1intx_free(&e1); ASN1intx_free(&e2); return ret; } #endif // ENABLE_REAL /* compare two doubles; return 0 iff equal */ int ASN1double_cmp(double d1, double d2) { return d1 < d2 ? -1 : d1 > d2 ? 1 : 0; } #ifdef ENABLE_EMBEDDED_PDV /* compare two embedded pdvs; return 0 iff equal */ int ASN1embeddedpdv_cmp(ASN1embeddedpdv_t *v1, ASN1embeddedpdv_t *v2) { int ret; if ((ret = (v1->identification.o - v2->identification.o))) return ret; switch (v1->identification.o) { case ASN1embeddedpdv_identification_syntaxes_o: if ((ret = ASN1objectidentifier_cmp( &v1->identification.u.syntaxes.abstract, &v2->identification.u.syntaxes.abstract))) return ret; if ((ret = ASN1objectidentifier_cmp( &v1->identification.u.syntaxes.transfer, &v2->identification.u.syntaxes.transfer))) return ret; break; case ASN1embeddedpdv_identification_syntax_o: if ((ret = ASN1objectidentifier_cmp(&v1->identification.u.syntax, &v2->identification.u.syntax))) return ret; break; case ASN1embeddedpdv_identification_presentation_context_id_o: if ((ret = (v1->identification.u.presentation_context_id - v2->identification.u.presentation_context_id))) return ret; break; case ASN1embeddedpdv_identification_context_negotiation_o: if ((ret = ( v1->identification.u.context_negotiation.presentation_context_id - v2->identification.u.context_negotiation.presentation_context_id))) return ret; if ((ret = ASN1objectidentifier_cmp( &v1->identification.u.context_negotiation.transfer_syntax, &v2->identification.u.context_negotiation.transfer_syntax))) return ret; break; case ASN1embeddedpdv_identification_transfer_syntax_o: if ((ret = ASN1objectidentifier_cmp( &v1->identification.u.transfer_syntax, &v2->identification.u.transfer_syntax))) return ret; break; case ASN1embeddedpdv_identification_fixed_o: break; } if ((ret = (v1->data_value.o - v2->data_value.o))) return ret; switch (v1->data_value.o) { case ASN1embeddedpdv_data_value_notation_o: if ((ret = ASN1open_cmp(&v1->data_value.u.notation, &v2->data_value.u.notation))) return ret; break; case ASN1embeddedpdv_data_value_encoded_o: if ((ret = ASN1bitstring_cmp(&v1->data_value.u.encoded, &v2->data_value.u.encoded, 0))) return ret; break; } return 0; } #endif // ENABLE_EMBEDDED_PDV /* compare two zero-terminated strings; return 0 iff equal */ int ASN1ztcharstring_cmp(ASN1ztcharstring_t v1, ASN1ztcharstring_t v2) { if (v1 && v2) { return lstrcmpA(v1, v2); } return v1 ? 1 : -1; } /* compare two zero-terminated 16 bit strings; return 0 iff equal */ int ASN1ztchar16string_cmp(ASN1ztchar16string_t v1, ASN1ztchar16string_t v2) { for (;;) { if (!*v1 || !*v2 || *v1 != *v2) return *v1 - *v2; v1++; v2++; } } /* compare two zero-terminated 32 bit strings; return 0 iff equal */ int ASN1ztchar32string_cmp(ASN1ztchar32string_t v1, ASN1ztchar32string_t v2) { for (;;) { if (!*v1 || !*v2 || *v1 != *v2) return *v1 - *v2; v1++; v2++; } } /* compare two strings; return 0 iff equal */ int ASN1charstring_cmp(ASN1charstring_t *v1, ASN1charstring_t *v2) { ASN1uint32_t i, l; l = v1->length; if (v2->length > l) l = v2->length; for (i = 0; i < l; i++) { if (v1->value[i] != v2->value[i]) return v1->value[i] - v2->value[i]; } return v1->length - v2->length; } /* compare two 16 bit strings; return 0 iff equal */ int ASN1char16string_cmp(ASN1char16string_t *v1, ASN1char16string_t *v2) { ASN1uint32_t i, l; l = v1->length; if (v2->length > l) l = v2->length; for (i = 0; i < l; i++) { if (v1->value[i] != v2->value[i]) return v1->value[i] - v2->value[i]; } return v1->length - v2->length; } /* compare two 32 bit strings; return 0 iff equal */ int ASN1char32string_cmp(ASN1char32string_t *v1, ASN1char32string_t *v2) { ASN1uint32_t i, l; l = v1->length; if (v2->length > l) l = v2->length; for (i = 0; i < l; i++) { if (v1->value[i] != v2->value[i]) return v1->value[i] - v2->value[i]; } return v1->length - v2->length; } #ifdef ENABLE_GENERALIZED_CHAR_STR /* compare two character strings; return 0 iff equal */ int ASN1characterstring_cmp(ASN1characterstring_t *v1, ASN1characterstring_t *v2) { int ret; if ((ret = (v1->identification.o - v2->identification.o))) return ret; switch (v1->identification.o) { case ASN1characterstring_identification_syntaxes_o: if ((ret = ASN1objectidentifier_cmp( &v1->identification.u.syntaxes.abstract, &v2->identification.u.syntaxes.abstract))) return ret; if ((ret = ASN1objectidentifier_cmp( &v1->identification.u.syntaxes.transfer, &v2->identification.u.syntaxes.transfer))) return ret; break; case ASN1characterstring_identification_syntax_o: if ((ret = ASN1objectidentifier_cmp(&v1->identification.u.syntax, &v2->identification.u.syntax))) return ret; break; case ASN1characterstring_identification_presentation_context_id_o: if ((ret = (v1->identification.u.presentation_context_id - v2->identification.u.presentation_context_id))) return ret; break; case ASN1characterstring_identification_context_negotiation_o: if ((ret = ( v1->identification.u.context_negotiation.presentation_context_id - v2->identification.u.context_negotiation.presentation_context_id))) return ret; if ((ret = ASN1objectidentifier_cmp( &v1->identification.u.context_negotiation.transfer_syntax, &v2->identification.u.context_negotiation.transfer_syntax))) return ret; break; case ASN1characterstring_identification_transfer_syntax_o: if ((ret = ASN1objectidentifier_cmp( &v1->identification.u.transfer_syntax, &v2->identification.u.transfer_syntax))) return ret; break; case ASN1characterstring_identification_fixed_o: break; } if ((ret = (v1->data_value.o - v2->data_value.o))) return ret; switch (v1->data_value.o) { case ASN1characterstring_data_value_notation_o: if ((ret = ASN1open_cmp(&v1->data_value.u.notation, &v2->data_value.u.notation))) return ret; break; case ASN1characterstring_data_value_encoded_o: if ((ret = ASN1octetstring_cmp(&v1->data_value.u.encoded, &v2->data_value.u.encoded))) return ret; break; } return 0; } #endif // ENABLE_GENERALIZED_CHAR_STR /* compare two utc times; return 0 iff equal */ int ASN1utctime_cmp(ASN1utctime_t *v1, ASN1utctime_t *v2) { if (v1->universal != v2->universal || v1->diff != v2->diff) return 1; if (v1->year != v2->year) return v1->year - v2->year; if (v1->month != v2->month) return v1->month - v2->month; if (v1->day != v2->day) return v1->day - v2->day; if (v1->hour != v2->hour) return v1->hour - v2->hour; if (v1->minute != v2->minute) return v1->minute - v2->minute; return v1->second - v2->second; } /* compare two generalized times; return 0 iff equal */ int ASN1generalizedtime_cmp(ASN1generalizedtime_t *v1, ASN1generalizedtime_t *v2) { if (v1->universal != v2->universal || v1->diff != v2->diff) return 1; if (v1->year != v2->year) return v1->year - v2->year; if (v1->month != v2->month) return v1->month - v2->month; if (v1->day != v2->day) return v1->day - v2->day; if (v1->hour != v2->hour) return v1->hour - v2->hour; if (v1->minute != v2->minute) return v1->minute - v2->minute; if (v1->second != v2->second) return v1->second - v2->second; return v1->millisecond - v2->millisecond; } /* compare two open type values; return 0 iff equal */ int ASN1open_cmp(ASN1open_t *v1, ASN1open_t *v2) { ASN1octetstring_t ostr1, ostr2; ostr1.length = v1->length; ostr1.value = v1->encoded; ostr2.length = v2->length; ostr2.value = v2->encoded; return ASN1octetstring_cmp(&ostr1, &ostr2); } /* compare two sequence of values with length-pointer representation */ /* return 0 iff equal */ int ASN1sequenceoflengthpointer_cmp(ASN1uint32_t l1, void *v1, ASN1uint32_t l2, void *v2, ASN1uint32_t size, int (*cmpfn)(void *v1, void *v2)) { int ret; ASN1octet_t *p1, *p2; if ((ret = (l1 - l2))) return ret; for (p1 = (ASN1octet_t *)v1, p2 = (ASN1octet_t *)v2; l1--; p1 += size, p2 += size) { if ((ret = cmpfn(p1, p2))) return ret; } return 0; } /* compare two sequence of values with singly-linked-list representation */ /* return 0 iff equal */ int ASN1sequenceofsinglylinkedlist_cmp(void *v1, void *v2, ASN1uint32_t off, int (*cmpfn)(void *, void *)) { int ret; ASN1octet_t *p1, *p2; for (p1 = (ASN1octet_t *)v1, p2 = (ASN1octet_t *)v2; p1 && p2; p1 = *(ASN1octet_t **)p1, p2 = *(ASN1octet_t **)p2) { if ((ret = cmpfn(p1 + off, p2 + off))) return ret; } return 0; } /* compare two sequence of values with doubly-linked-list representation */ /* return 0 iff equal */ int ASN1sequenceofdoublylinkedlist_cmp(void *v1, void *v2, ASN1uint32_t off, int (*cmpfn)(void *, void *)) { int ret; ASN1octet_t *p1, *p2; for (p1 = (ASN1octet_t *)v1, p2 = (ASN1octet_t *)v2; p1 && p2; p1 = *(ASN1octet_t **)p1, p2 = *(ASN1octet_t **)p2) { if ((ret = cmpfn(p1 + off, p2 + off))) return ret; } return 0; } /* compare two set of values with length-pointer representation */ /* return 0 iff equal */ int ASN1setoflengthpointer_cmp(ASN1uint32_t l1, void *v1, ASN1uint32_t l2, void *v2, ASN1uint32_t size, int (*cmpfn)(void *v1, void *v2)) { int ret; ASN1octet_t *p1, *p2, *found, *f; ASN1uint32_t l; if ((ret = (l1 - l2))) return ret; if (!l1) return 0; found = (ASN1octet_t *)MemAlloc(l1, UNKNOWN_MODULE); if (found) { memset(found, 0, l1); for (p1 = (ASN1octet_t *)v1; l1--; p1 += size) { for (p2 = (ASN1octet_t *)v2, l = l2, f = found; l; p2 += size, f++, l--) { if (!*f && !cmpfn(p1, p2)) { *f = 1; break; } } if (!l) { MemFree(found); return 1; } } MemFree(found); } return 0; } /* compare two set of values with singly-linked-list representation */ /* return 0 iff equal */ int ASN1setofsinglylinkedlist_cmp(void *v1, void *v2, ASN1uint32_t off, int (*cmpfn)(void *, void *)) { int ret; ASN1octet_t *p1, *p2, *found, *f; ASN1uint32_t l1, l2; for (p1 = (ASN1octet_t *)v1, l1 = 0; p1; p1 = *(ASN1octet_t **)p1) l1++; for (p2 = (ASN1octet_t *)v2, l2 = 0; p2; p2 = *(ASN1octet_t **)p2) l2++; if ((ret = (l1 - l2))) return ret; if (!l1) return 0; found = (ASN1octet_t *)MemAlloc(l1, UNKNOWN_MODULE); if (found) { memset(found, 0, l1); for (p1 = (ASN1octet_t *)v1; p1; p1 = *(ASN1octet_t **)p1) { for (p2 = (ASN1octet_t *)v2, f = found; p2; p2 = *(ASN1octet_t **)p2, f++) { if (!*f && !cmpfn(p1 + off, p2 + off)) { *f = 1; break; } } if (!p2) { MemFree(found); return 1; } } MemFree(found); } return 0; } /* compare two set of values with doubly-linked-list representation */ /* return 0 iff equal */ int ASN1setofdoublylinkedlist_cmp(void *v1, void *v2, ASN1uint32_t off, int (*cmpfn)(void *, void *)) { int ret; ASN1octet_t *p1, *p2, *found, *f; ASN1uint32_t l1, l2; for (p1 = (ASN1octet_t *)v1, l1 = 0; p1; p1 = *(ASN1octet_t **)p1) l1++; for (p2 = (ASN1octet_t *)v2, l2 = 0; p2; p2 = *(ASN1octet_t **)p2) l2++; if ((ret = (l1 - l2))) return ret; if (!l1) return 0; found = (ASN1octet_t *)MemAlloc(l1, UNKNOWN_MODULE); if (found) { memset(found, 0, l1); for (p1 = (ASN1octet_t *)v1; p1; p1 = *(ASN1octet_t **)p1) { for (p2 = (ASN1octet_t *)v2, f = found; p2; p2 = *(ASN1octet_t **)p2, f++) { if (!*f && !cmpfn(p1 + off, p2 + off)) { *f = 1; break; } } if (!p2) { MemFree(found); return 1; } } MemFree(found); } return 0; } #endif // defined(ENABLE_COMPARE) || defined(ENABLE_BER)