/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */ /* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */ // lonchanc: we seem to have a significant amount of memory leak // while dealing with real number and unlimited integers. // we definitely want to re-visit all the following routines carefully // in the future. // moreover, we need to make sure all the memory allocation and free // are either using encoding and decoding memory manager or kernel one. // need to make sure we do not mix them together. #include "precomp.h" #include #include #include /* builtin intx values */ ASN1octet_t ASN1intx_0_[] = { 0 }; ASN1intx_t ASN1intx_0 = { 1, ASN1intx_0_ }; ASN1octet_t ASN1intx_1_[] = { 1 }; ASN1intx_t ASN1intx_1 = { 1, ASN1intx_1_ }; ASN1octet_t ASN1intx_2_[] = { 2 }; ASN1intx_t ASN1intx_2 = { 1, ASN1intx_2_ }; ASN1octet_t ASN1intx_16_[] = { 16 }; ASN1intx_t ASN1intx_16 = { 1, ASN1intx_16_ }; ASN1octet_t ASN1intx_256_[] = { 1, 0 }; ASN1intx_t ASN1intx_256 = { 2, ASN1intx_256_ }; ASN1octet_t ASN1intx_64K_[] = { 1, 0, 0 }; ASN1intx_t ASN1intx_64K = { 3, ASN1intx_64K_ }; ASN1octet_t ASN1intx_1G_[] = { 64, 0, 0, 0 }; ASN1intx_t ASN1intx_1G = { 4, ASN1intx_1G_ }; /* add two intx values */ void ASN1intx_add(ASN1intx_t *dst, ASN1intx_t *arg1, ASN1intx_t *arg2) { ASN1octet_t *v; int l; int s1, s2; int o1, o2; int i; int c; int w; /* get signs */ s1 = arg1->value[0] > 0x7f ? 0xff : 0x00; s2 = arg2->value[0] > 0x7f ? 0xff : 0x00; /* result length will be <= l */ l = arg1->length > arg2->length ? arg1->length + 1 : arg2->length + 1; /* offset into values */ o1 = l - arg1->length; o2 = l - arg2->length; /* allocate result */ v = (ASN1octet_t *)malloc(l); /* clear carry bit */ c = 0; /* add octet by octet */ for (i = l - 1; i >= 0; i--) { w = (i >= o1 ? arg1->value[i - o1] : s1) + (i >= o2 ? arg2->value[i - o2] : s2) + c; v[i] = (ASN1octet_t)w; c = w > 0xff; } /* octets which may shall dropped */ w = v[0] > 0x7f ? 0xff : 0x00; /* count octets that shall be dropped */ for (i = 0; i < l - 1; i++) { if (v[i] != w) break; } if ((v[i] ^ w) & 0x80) i--; /* allocate and copy result */ dst->length = l - i; dst->value = (ASN1octet_t *)malloc(l - i); memcpy(dst->value, v + i, l - i); free(v); } /* substract two intx values */ void ASN1intx_sub(ASN1intx_t *dst, ASN1intx_t *arg1, ASN1intx_t *arg2) { ASN1octet_t *v; int l; int s1, s2; int o1, o2; int i; int c; int w; /* get signs */ s1 = arg1->value[0] > 0x7f ? 0xff : 0x00; s2 = arg2->value[0] > 0x7f ? 0xff : 0x00; /* result length will be <= l */ l = arg1->length > arg2->length ? arg1->length + 1 : arg2->length + 1; /* offset into values */ o1 = l - arg1->length; o2 = l - arg2->length; /* allocate result */ v = (ASN1octet_t *)malloc(l); /* clear borrow bit */ c = 0; /* substract octet by octet */ for (i = l - 1; i >= 0; i--) { w = (i >= o1 ? arg1->value[i - o1] : s1) - (i >= o2 ? arg2->value[i - o2] : s2) - c; v[i] = (ASN1octet_t)w; c = w < 0; } /* octets which may shall dropped */ w = v[0] > 0x7f ? 0xff : 0x00; /* count octets that shall be dropped */ for (i = 0; i < l - 1; i++) { if (v[i] != w) break; } if ((v[i] ^ w) & 0x80) i--; // lonchanc: do we forget to free dst->value??? // in case that dst and arg1 are identical. for instance, // ASN1BEREncReal() calls ASN1intx_sub(&exponent, &exponent, &help); /* allocate and copy result */ dst->length = l - i; dst->value = (ASN1octet_t *)malloc(l - i); memcpy(dst->value, v + i, l - i); free(v); } /* add one octet to an intx */ void ASN1intx_addoctet(ASN1intx_t *dst, ASN1intx_t *arg1, ASN1octet_t arg2) { ASN1octet_t *v; int l; int i; int c; int w; /* result length will be <= l */ l = arg1->length + 1; /* allocate result */ v = (ASN1octet_t *)malloc(l); /* add octet by octet */ c = arg2; for (i = l - 2; i >= 0; i--) { w = arg1->value[i] + c; v[i + 1] = (ASN1octet_t)w; c = (w > 0xff); } v[0] = arg1->value[0] > 0x7f ? (ASN1octet_t)(0xff + c) : (ASN1octet_t)c; /* octets which may shall dropped */ w = v[0] > 0x7f ? 0xff : 0x00; /* count octets that shall be dropped */ for (i = 0; i < l - 1; i++) { if (v[i] != w) break; } if ((v[i] ^ w) & 0x80) i--; /* allocate and copy result */ dst->length = l - i; dst->value = (ASN1octet_t *)malloc(l - i); memcpy(dst->value, v + i, l - i); free(v); } /* substract one octet to an intx */ void ASN1intx_suboctet(ASN1intx_t *dst, ASN1intx_t *arg1, ASN1octet_t arg2) { ASN1octet_t *v; int l; int i; int c; int w; /* result length will be <= l */ l = arg1->length + 1; /* allocate result */ v = (ASN1octet_t *)malloc(l); /* substract octet by octet */ c = arg2; for (i = l - 2; i >= 0; i--) { w = arg1->value[i] - c; v[i + 1] = (ASN1octet_t)w; c = (w < 0); } v[0] = arg1->value[0] > 0x7f ? (ASN1octet_t)(0xff - c) : (ASN1octet_t)c; /* octets which may shall dropped */ w = v[0] > 0x7f ? 0xff : 0x00; /* count octets that shall be dropped */ for (i = 0; i < l - 1; i++) { if (v[i] != w) break; } if ((v[i] ^ w) & 0x80) i--; /* allocate and copy result */ dst->length = l - i; dst->value = (ASN1octet_t *)malloc(l - i); memcpy(dst->value, v + i, l - i); free(v); } /* multiply intx by an octet */ void ASN1intx_muloctet(ASN1intx_t *dst, ASN1intx_t *arg1, ASN1octet_t arg2) { ASN1octet_t *v; int l; int c; int i; int w; /* result length will be <= l */ l = arg1->length + 1; /* allocate result */ v = (ASN1octet_t *)malloc(l); /* multiply octet by octet */ c = 0; for (i = l - 2; i >= 0; i--) { w = arg1->value[i] * arg2 + c; v[i + 1] = (ASN1octet_t)w; c = w >> 8; } v[0] = (ASN1octet_t)(arg1->value[0] > 0x7f ? 0xff * arg2 + c : c); /* octets which may shall dropped */ w = v[0] > 0x7f ? 0xff : 0x00; /* count octets that shall be dropped */ for (i = 0; i < l - 1; i++) { if (v[i] != w) break; } if ((v[i] ^ w) & 0x80) i--; /* allocate and copy result */ dst->length = l - i; dst->value = (ASN1octet_t *)malloc(l - i); memcpy(dst->value, v + i, l - i); free(v); } /* increment an intx */ void ASN1intx_inc(ASN1intx_t *val) { ASN1octet_t *v; int l; int i; int w; /* result length will be <= l */ l = val->length + 1; /* allocate result */ v = (ASN1octet_t *)malloc(l); /* copy value */ memcpy(v + 1, val->value, l - 1); free(val->value); v[0] = v[1] > 0x7f ? 0xff : 0x00; /* increment value */ for (i = l - 1; i >= 0; i--) { if (++v[i]) break; } /* octets which may shall dropped */ w = v[0] > 0x7f ? 0xff : 0x00; /* count octets that shall be dropped */ for (i = 0; i < l - 1; i++) { if (v[i] != w) break; } if ((v[i] ^ w) & 0x80) i--; /* allocate and copy result */ val->length = l - i; val->value = (ASN1octet_t *)malloc(l - i); memcpy(val->value, v + i, l - i); free(v); } /* decrement an intx */ void ASN1intx_dec(ASN1intx_t *val) { ASN1octet_t *v; int l; int i; int w; /* result length will be <= l */ l = val->length + 1; /* allocate result */ v = (ASN1octet_t *)malloc(l); /* copy value */ memcpy(v + 1, val->value, l - 1); free(val->value); v[0] = v[1] > 0x7f ? 0xff : 0x00; /* decrement value */ for (i = l - 1; i >= 0; i--) { if (v[i]--) break; } /* octets which may shall dropped */ w = v[0] > 0x7f ? 0xff : 0x00; /* count octets that shall be dropped */ for (i = 0; i < l - 1; i++) { if (v[i] != w) break; } if ((v[i] ^ w) & 0x80) i--; /* allocate and copy result */ val->length = l - i; val->value = (ASN1octet_t *)malloc(l - i); memcpy(val->value, v + i, l - i); free(v); } /* negate an intx value */ void ASN1intx_neg(ASN1intx_t *dst, ASN1intx_t *arg) { ASN1uint32_t i; /* duplicate value */ ASN1intx_dup(dst, arg); /* ones complement */ for (i = 0; i < dst->length; i++) dst->value[i] = ~dst->value[i]; /* and increment */ ASN1intx_inc(dst); } /* returns floor(log2(arg - 1)) */ ASN1uint32_t ASN1intx_log2(ASN1intx_t *arg) { ASN1uint32_t i; ASN1intx_t v; ASN1uint32_t n; ASN1intx_dup(&v, arg); ASN1intx_dec(&v); if (v.value[0] > 0x7f) { ASN1intx_free(&v); return 0; } for (i = 0; i < v.length; i++) { if (v.value[i]) break; } if (i >= v.length) { n = 0; } else if (v.value[i] > 0x7f) { n = 8 * (v.length - i - 1) + 8; } else if (v.value[i] > 0x3f) { n = 8 * (v.length - i - 1) + 7; } else if (v.value[i] > 0x1f) { n = 8 * (v.length - i - 1) + 6; } else if (v.value[i] > 0x0f) { n = 8 * (v.length - i - 1) + 5; } else if (v.value[i] > 0x07) { n = 8 * (v.length - i - 1) + 4; } else if (v.value[i] > 0x03) { n = 8 * (v.length - i - 1) + 3; } else if (v.value[i] > 0x01) { n = 8 * (v.length - i - 1) + 2; } else { n = 8 * (v.length - i - 1) + 1; } ASN1intx_free(&v); return n; } /* returns floor(log2(arg - 1)) */ ASN1uint32_t ASN1uint32_log2(ASN1uint32_t arg) { ASN1uint32_t i; arg--; for (i = 32; i != 0; i--) { if (arg & (1 << (i - 1))) break; } return i; } /* returns floor(log256(arg - 1)) */ ASN1uint32_t ASN1intx_log256(ASN1intx_t *arg) { ASN1uint32_t i; ASN1intx_t v; ASN1intx_dup(&v, arg); ASN1intx_dec(&v); if (v.value[0] > 0x7f) { ASN1intx_free(&v); return 0; } for (i = 0; i < v.length; i++) { if (v.value[i]) break; } ASN1intx_free(&v); return v.length - i; } /* returns floor(log256(arg - 1)) */ ASN1uint32_t ASN1uint32_log256(ASN1uint32_t arg) { if (arg > 0x10000) { if (arg > 0x1000000) return 4; return 3; } if (arg > 0x100) return 2; if (arg > 1) return 1; return 0; } /* compare two intx values; return 0 iff equal */ ASN1int32_t ASN1intx_cmp(ASN1intx_t *arg1, ASN1intx_t *arg2) { int s1, s2; int o1, o2; int l; int i; int d; s1 = arg1->value[0] > 0x7f ? 0xff : 0x00; s2 = arg2->value[0] > 0x7f ? 0xff : 0x00; if (s1 != s2) return s1 == 0xff ? -1 : 1; l = arg1->length > arg2->length ? arg1->length : arg2->length; o1 = l - arg1->length; o2 = l - arg2->length; for (i = 0; i < l; i++) { d = (i >= o1 ? arg1->value[i - o1] : s1) - (i >= o2 ? arg2->value[i - o2] : s2); if (d) return d; } return 0; } /* create an intx value from an uint32 value */ void ASN1intx_setuint32(ASN1intx_t *dst, ASN1uint32_t val) { ASN1octet_t o[5], *v = o; int n = 5; v[0] = 0; v[1] = (ASN1octet_t)(val >> 24); v[2] = (ASN1octet_t)(val >> 16); v[3] = (ASN1octet_t)(val >> 8); v[4] = (ASN1octet_t)(val); while (n > 1 && !*v && v[1] <= 0x7f) { n--; v++; } dst->length = n; dst->value = (ASN1octet_t *)malloc(n); memcpy(dst->value, v, n); } /* create an intx value from an int32 value */ void ASN1intx_setint32(ASN1intx_t *dst, ASN1int32_t val) { ASN1octet_t o[5], *v = o; int n = 5; v[0] = (ASN1octet_t)(val < 0 ? 0xff : 0x00); v[1] = (ASN1octet_t)(val >> 24); v[2] = (ASN1octet_t)(val >> 16); v[3] = (ASN1octet_t)(val >> 8); v[4] = (ASN1octet_t)(val); while (n > 1 && ((!*v && v[1] <= 0x7f) || (*v == 0xff && v[1] > 0x7f))) { n--; v++; } dst->length = n; dst->value = (ASN1octet_t *)malloc(n); memcpy(dst->value, v, n); } /* copy constructor */ void ASN1intx_dup(ASN1intx_t *dst, ASN1intx_t *val) { dst->length = val->length; dst->value = (ASN1octet_t *)malloc(val->length); memcpy(dst->value, val->value, val->length); } /* free an intx value */ void ASN1intx_free(ASN1intx_t *val) { free(val->value); } #ifdef HAS_SIXTYFOUR_BITS /* convert an intx value to a uint64 value */ ASN1uint64_t ASN1intx2uint64(ASN1intx_t *val) { switch (val->length) { case 1: return (ASN1uint64_t)val->value[val->length - 1]; case 2: return (ASN1uint64_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8)); case 3: return (ASN1uint64_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8) | ((ASN1uint32_t)val->value[val->length - 3] << 16)); case 4: return (ASN1uint64_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8) | ((ASN1uint32_t)val->value[val->length - 3] << 16) | ((ASN1uint32_t)val->value[val->length - 4] << 24)); case 5: return (ASN1uint64_t)(val->value[val->length - 1] | ((ASN1uint64_t)val->value[val->length - 2] << 8) | ((ASN1uint64_t)val->value[val->length - 3] << 16) | ((ASN1uint64_t)val->value[val->length - 4] << 24) | ((ASN1uint64_t)val->value[val->length - 5] << 32)); case 6: return (ASN1uint64_t)(val->value[val->length - 1] | ((ASN1uint64_t)val->value[val->length - 2] << 8) | ((ASN1uint64_t)val->value[val->length - 3] << 16) | ((ASN1uint64_t)val->value[val->length - 4] << 24) | ((ASN1uint64_t)val->value[val->length - 5] << 32) | ((ASN1uint64_t)val->value[val->length - 6] << 40)); case 7: return (ASN1uint64_t)(val->value[val->length - 1] | ((ASN1uint64_t)val->value[val->length - 2] << 8) | ((ASN1uint64_t)val->value[val->length - 3] << 16) | ((ASN1uint64_t)val->value[val->length - 4] << 24) | ((ASN1uint64_t)val->value[val->length - 5] << 32) | ((ASN1uint64_t)val->value[val->length - 6] << 40) | ((ASN1uint64_t)val->value[val->length - 7] << 48)); default: return (ASN1uint64_t)(val->value[val->length - 1] | ((ASN1uint64_t)val->value[val->length - 2] << 8) | ((ASN1uint64_t)val->value[val->length - 3] << 16) | ((ASN1uint64_t)val->value[val->length - 4] << 24) | ((ASN1uint64_t)val->value[val->length - 5] << 32) | ((ASN1uint64_t)val->value[val->length - 6] << 40) | ((ASN1uint64_t)val->value[val->length - 7] << 48) | ((ASN1uint64_t)val->value[val->length - 8] << 56)); } } #endif /* check if intx value is a uint64 value */ int ASN1intxisuint64(ASN1intx_t *val) { if (val->value[0] > 0x7f) return 0; return ASN1intx_uoctets(val) <= 8; } #ifdef HAS_SIXTYFOUR_BITS /* convert an intx value to a int64 value */ ASN1int64_t ASN1intx2int64(ASN1intx_t *val) { switch (val->length) { case 1: return (ASN1int64_t)(ASN1int8_t)val->value[val->length - 1]; case 2: return (ASN1int64_t)(ASN1int16_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8)); case 3: return (ASN1int64_t)(ASN1int32_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8) | ((ASN1uint32_t)val->value[val->length - 3] << 16) | ((ASN1uint32_t)val->value[val->length - 3] > 0x7f ? 0xffffffffff000000LL : 0)); case 4: return (ASN1int64_t)(ASN1int32_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8) | ((ASN1uint32_t)val->value[val->length - 3] << 16) | ((ASN1uint32_t)val->value[val->length - 4] << 24)); case 5: return (ASN1int64_t)(val->value[val->length - 1] | ((ASN1uint64_t)val->value[val->length - 2] << 8) | ((ASN1uint64_t)val->value[val->length - 3] << 16) | ((ASN1uint64_t)val->value[val->length - 4] << 24) | ((ASN1uint64_t)val->value[val->length - 5] << 32) | ((ASN1uint64_t)val->value[val->length - 5] > 0x7f ? 0xffffff0000000000LL : 0)); case 6: return (ASN1int64_t)(val->value[val->length - 1] | ((ASN1uint64_t)val->value[val->length - 2] << 8) | ((ASN1uint64_t)val->value[val->length - 3] << 16) | ((ASN1uint64_t)val->value[val->length - 4] << 24) | ((ASN1uint64_t)val->value[val->length - 5] << 32) | ((ASN1uint64_t)val->value[val->length - 6] << 40) | ((ASN1uint64_t)val->value[val->length - 6] > 0x7f ? 0xffff000000000000LL : 0)); case 7: return (ASN1int64_t)((ASN1uint64_t)val->value[val->length - 1] | ((ASN1uint64_t)val->value[val->length - 2] << 8) | ((ASN1uint64_t)val->value[val->length - 3] << 16) | ((ASN1uint64_t)val->value[val->length - 4] << 24) | ((ASN1uint64_t)val->value[val->length - 5] << 32) | ((ASN1uint64_t)val->value[val->length - 6] << 40) | ((ASN1uint64_t)val->value[val->length - 7] << 48) | ((ASN1uint64_t)val->value[val->length - 7] > 0x7f ? 0xff00000000000000LL : 0)); default: return (ASN1int64_t)((ASN1uint64_t)val->value[val->length - 1] | ((ASN1uint64_t)val->value[val->length - 2] << 8) | ((ASN1uint64_t)val->value[val->length - 3] << 16) | ((ASN1uint64_t)val->value[val->length - 4] << 24) | ((ASN1uint64_t)val->value[val->length - 5] << 32) | ((ASN1uint64_t)val->value[val->length - 6] << 40) | ((ASN1uint64_t)val->value[val->length - 7] << 48) | ((ASN1uint64_t)val->value[val->length - 8] << 56)); } } #endif /* check if intx value is an int64 value */ int ASN1intxisint64(ASN1intx_t *val) { return ASN1intx_octets(val) <= 8; } /* convert intx value to uint32 value */ ASN1uint32_t ASN1intx2uint32(ASN1intx_t *val) { switch (val->length) { case 1: return (ASN1uint32_t)val->value[val->length - 1]; case 2: return (ASN1uint32_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8)); case 3: return (ASN1uint32_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8) | ((ASN1uint32_t)val->value[val->length - 3] << 16)); default: return (ASN1uint32_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8) | ((ASN1uint32_t)val->value[val->length - 3] << 16) | ((ASN1uint32_t)val->value[val->length - 4] << 24)); } } /* check if intx value is an uint32 value */ int ASN1intxisuint32(ASN1intx_t *val) { if (val->value[0] > 0x7f) return 0; return ASN1intx_uoctets(val) <= 4; } /* convert intx value to int32 value */ ASN1int32_t ASN1intx2int32(ASN1intx_t *val) { switch (val->length) { case 1: return (ASN1int32_t)(ASN1int8_t)val->value[val->length - 1]; case 2: return (ASN1int32_t)(ASN1int16_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8)); case 3: return (ASN1int32_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8) | ((ASN1uint32_t)val->value[val->length - 3] << 16) | ((ASN1uint32_t)val->value[val->length - 3] > 0x7f ? 0xff000000 : 0)); default: return (ASN1int32_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8) | ((ASN1uint32_t)val->value[val->length - 3] << 16) | ((ASN1uint32_t)val->value[val->length - 4] << 24)); } } /* check if intx value is an int32 value */ int ASN1intxisint32(ASN1intx_t *val) { return ASN1intx_octets(val) <= 4; } /* convert intx value to uint16 value */ ASN1uint16_t ASN1intx2uint16(ASN1intx_t *val) { if (val->length == 1) return (ASN1uint16_t)val->value[val->length - 1]; return (ASN1uint16_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8)); } /* check if intx value is an uint16 value */ int ASN1intxisuint16(ASN1intx_t *val) { if (val->value[0] > 0x7f) return 0; return ASN1intx_uoctets(val) <= 2; } /* convert intx value to int16 value */ ASN1int16_t ASN1intx2int16(ASN1intx_t *val) { if (val->length == 1) return (ASN1int16_t)(ASN1int8_t)val->value[val->length - 1]; return (ASN1int16_t)(val->value[val->length - 1] | ((ASN1uint32_t)val->value[val->length - 2] << 8)); } /* check if intx value is an int16 value */ int ASN1intxisint16(ASN1intx_t *val) { return ASN1intx_octets(val) <= 2; } /* convert intx value to uint8 value */ ASN1uint8_t ASN1intx2uint8(ASN1intx_t *val) { return (ASN1uint8_t)val->value[val->length - 1]; } /* check if intx value is an uint8 value */ int ASN1intxisuint8(ASN1intx_t *val) { if (val->value[0] > 0x7f) return 0; return ASN1intx_uoctets(val) <= 1; } /* convert intx value to int8 value */ ASN1int8_t ASN1intx2int8(ASN1intx_t *val) { return (ASN1int8_t)val->value[val->length - 1]; } /* check if intx value is an int8 value */ int ASN1intxisint8(ASN1intx_t *val) { return ASN1intx_octets(val) <= 1; } /* count octets for a signed encoding of an intx value */ ASN1uint32_t ASN1intx_octets(ASN1intx_t *val) { ASN1uint32_t i; ASN1uint32_t s; s = val->value[0] > 0x7f ? 0xff : 0x00; for (i = 0; i < val->length; i++) { if (val->value[i] != s) break; } if (i && ((val->value[i] ^ s) & 0x80)) i--; return val->length - i; } /* count octets for unsigned encoding of an unsigned intx value */ ASN1uint32_t ASN1intx_uoctets(ASN1intx_t *val) { ASN1uint32_t i; for (i = 0; i < val->length; i++) { if (val->value[i]) break; } return val->length - i; } /* count octets for signed encoding of an uint32 value */ ASN1uint32_t ASN1uint32_octets(ASN1uint32_t val) { if (val >= 0x8000) { if (val >= 0x800000) { if (val >= 0x80000000) return 5; return 4; } return 3; } if (val >= 0x80) return 2; return 1; } /* count octets for unsigned encoding of an uint32 value */ ASN1uint32_t ASN1uint32_uoctets(ASN1uint32_t val) { if (val >= 0x10000) { if (val >= 0x1000000) return 4; return 3; } if (val >= 0x100) return 2; return 1; } /* count octets for signed encoding of an int32 value */ ASN1uint32_t ASN1int32_octets(ASN1int32_t val) { if (val >= 0) { if (val >= 0x8000) { if (val >= 0x800000) return 4; return 3; } if (val >= 0x80) return 2; return 1; } if (val < -0x8000) { if (val < -0x800000) return 4; return 3; } if (val < -0x80) return 2; return 1; } /* convert an intx value into a double */ double ASN1intx2double(ASN1intx_t *val) { double ret; ASN1uint32_t i; if (val->value[0] > 0x7f) ret = (double)(val->value[0] - 0x100); else ret = (double)val->value[0]; for (i = 1; i < val->length; i++) { ret = ret * 256.0 + (double)val->value[i]; } return ret; }