|
|
/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */ /* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
#include "precomp.h"
#ifdef ENABLE_BER
#include <math.h>
static const char bitmsk2[] = { (const char) 0x00, (const char) 0x80, (const char) 0xc0, (const char) 0xe0, (const char) 0xf0, (const char) 0xf8, (const char) 0xfc, (const char) 0xfe };
/* decode bit string value */ int _BERDecBitString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1bitstring_t *val, ASN1uint32_t fNoCopy) { ASN1uint32_t constructed, len, infinite; ASN1bitstring_t b; ASN1decoding_t dd; ASN1octet_t *di;
/* skip tag */ if (ASN1BERDecTag(dec, tag, &constructed)) { /* get length */ if (ASN1BERDecLength(dec, &len, &infinite)) { if (constructed) { /* constructed? then start decoding of constructed value */ val->length = 0; if (_BERDecConstructed(dec, len, infinite, &dd, &di)) { while (ASN1BERDecNotEndOfContents(dd, di)) { if (_BERDecBitString(dd, 0x3, &b, fNoCopy)) { if (b.length) { if (fNoCopy) { *val = b; break; // break out the loop because nocopy cannot have multiple constructed streams
}
/* resize value */ val->value = (ASN1octet_t *)DecMemReAlloc(dd, val->value, (val->length + b.length + 7) / 8); if (val->value) { /* concat bit strings */ ASN1bitcpy(val->value, val->length, b.value, 0, b.length); val->length += b.length; if (val->length & 7) val->value[val->length / 8] &= bitmsk2[val->length & 7];
/* free unused bit string */ DecMemFree(dec, b.value); } else { return 0; } } } } // while
return ASN1BERDecEndOfContents(dec, dd, di); } } else { /* primitive? then copy value */ if (!len) { val->length = 0; val->value = NULL; return 1; } else { if (*dec->pos < 8) { len--; // skip over the initial octet; len is now the actual length of octets
val->length = len * 8 - *dec->pos++; if (fNoCopy) { val->value = dec->pos; dec->pos += len; return 1; } else { if (val->length) { val->value = (ASN1octet_t *)DecMemAlloc(dec, (val->length + 7) / 8); if (val->value) { CopyMemory(val->value, dec->pos, len); if (val->length & 7) val->value[len - 1] &= bitmsk2[val->length & 7]; dec->pos += len; return 1; } } else { val->value = NULL; return 1; } } } else { ASN1DecSetError(dec, ASN1_ERR_CORRUPT); } } } } } return 0; }
/* decode bit string value, making copy */ int ASN1BERDecBitString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1bitstring_t *val) { return _BERDecBitString(dec, tag, val, FALSE); }
/* decode bit string value, no copy */ int ASN1BERDecBitString2(ASN1decoding_t dec, ASN1uint32_t tag, ASN1bitstring_t *val) { return _BERDecBitString(dec, tag, val, TRUE); }
/* decode string value */ int ASN1BERDecCharString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1charstring_t *val) { ASN1uint32_t constructed, len, infinite; ASN1charstring_t c; ASN1decoding_t dd; ASN1octet_t *di;
/* skip tag */ if (ASN1BERDecTag(dec, tag, &constructed)) { /* get length */ if (ASN1BERDecLength(dec, &len, &infinite)) { if (constructed) { /* constructed? then start decoding of constructed value */ val->length = 0; if (_BERDecConstructed(dec, len, infinite, &dd, &di)) { while (ASN1BERDecNotEndOfContents(dd, di)) { if (ASN1BERDecCharString(dd, 0x4, &c)) { if (c.length) { /* resize value */ val->value = (char *)DecMemReAlloc(dd, val->value, val->length + c.length); if (val->value) { /* concat strings */ CopyMemory(val->value + val->length, c.value, c.length); val->length += c.length;
/* free unused string */ DecMemFree(dec, c.value); } else { return 0; } } } else { return 0; } } // while
return ASN1BERDecEndOfContents(dec, dd, di); } } else { /* primitive? then copy value */ val->length = len; if (len) { val->value = (char *)DecMemAlloc(dec, len+1); if (val->value) { CopyMemory(val->value, dec->pos, len); dec->pos += len; val->value[len] = 0; return 1; } } else { val->value = NULL; return 1; } } } } return 0; }
/* decode 16 bit string value */ int ASN1BERDecChar16String(ASN1decoding_t dec, ASN1uint32_t tag, ASN1char16string_t *val) { ASN1uint32_t constructed, len, infinite; ASN1char16string_t c; ASN1decoding_t dd; ASN1octet_t *di; ASN1uint32_t i;
/* skip tag */ if (ASN1BERDecTag(dec, tag, &constructed)) { /* get length */ if (ASN1BERDecLength(dec, &len, &infinite)) { if (constructed) { /* constructed? then start decoding of constructed value */ val->length = 0; if (_BERDecConstructed(dec, len, infinite, &dd, &di)) { while (ASN1BERDecNotEndOfContents(dd, di)) { if (ASN1BERDecChar16String(dd, 0x4, &c)) { if (c.length) { /* resize value */ val->value = (ASN1char16_t *)DecMemReAlloc(dd, val->value, (val->length + c.length) * sizeof(ASN1char16_t)); if (val->value) { /* concat strings */ CopyMemory(val->value + val->length, c.value, c.length * sizeof(ASN1char16_t)); val->length += c.length;
/* free unused string */ DecMemFree(dec, c.value); } else { return 0; } } } else { return 0; } } return ASN1BERDecEndOfContents(dec, dd, di); } } else { /* primitive? then copy value */ DecAssert(dec, 2 * sizeof(ASN1octet_t) == sizeof(ASN1char16_t)); len = len >> 1; // divided by 2
val->length = len; if (len) { val->value = (ASN1char16_t *)DecMemAlloc(dec, (len+1) * sizeof(ASN1char16_t)); if (val->value) { for (i = 0; i < len; i++) { val->value[i] = (*dec->pos << 8) | dec->pos[1]; dec->pos += 2; } val->value[len] = 0; return 1; } } else { val->value = NULL; return 1; } } } } return 0; }
/* decode 32 bit string value */ int ASN1BERDecChar32String(ASN1decoding_t dec, ASN1uint32_t tag, ASN1char32string_t *val) { ASN1uint32_t constructed, len, infinite; ASN1char32string_t c; ASN1decoding_t dd; ASN1octet_t *di; ASN1uint32_t i;
/* skip tag */ if (ASN1BERDecTag(dec, tag, &constructed)) { /* get length */ if (ASN1BERDecLength(dec, &len, &infinite)) { if (constructed) { /* constructed? then start decoding of constructed value */ val->length = 0; if (_BERDecConstructed(dec, len, infinite, &dd, &di)) { while (ASN1BERDecNotEndOfContents(dd, di)) { if (ASN1BERDecChar32String(dd, 0x4, &c)) { if (c.length) { /* resize value */ val->value = (ASN1char32_t *)DecMemReAlloc(dd, val->value, (val->length + c.length) * sizeof(ASN1char32_t)); if (val->value) { /* concat strings */ CopyMemory(val->value + val->length, c.value, c.length * sizeof(ASN1char32_t)); val->length += c.length;
/* free unused string */ DecMemFree(dec, c.value); } else { return 0; } } } else { return 0; } } return ASN1BERDecEndOfContents(dec, dd, di); } } else { /* primitive? then copy value */ DecAssert(dec, 4 * sizeof(ASN1octet_t) == sizeof(ASN1char32_t)); len = len >> 2; // divided by 4
val->length = len; if (len) { val->value = (ASN1char32_t *)DecMemAlloc(dec, (len+1) * sizeof(ASN1char32_t)); if (val->value) { for (i = 0; i < len; i++) { val->value[i] = (*dec->pos << 24) | (dec->pos[1] << 16) | (dec->pos[2] << 8) | dec->pos[3];; dec->pos += 4; } val->value[len] = 0; return 1; } } else { val->value = NULL; return 1; } } } } return 0; }
#ifdef ENABLE_GENERALIZED_CHAR_STR
/* decode character string value */ int ASN1BERDecCharacterString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1characterstring_t *val) { ASN1INTERNdecoding_t d = (ASN1INTERNdecoding_t) dec; ASN1uint32_t constructed, len, infinite; ASN1uint32_t index; ASN1characterstring_identification_t *identification; ASN1decoding_t dd, dd2, dd3; ASN1octet_t *di, *di2, *di3;
/* skip tag */ if (!ASN1BERDecTag(dec, tag, &constructed)) return 0;
if (constructed) { /* constructed? CS-A encoded: */ /* get length */ if (!ASN1BERDecLength(dec, &len, &infinite)) return 0;
/* start decoding of constructed value */ if (! _BERDecConstructed(dec, len, infinite, &dd, &di)) return 0; if (!ASN1BERDecU32Val(dd, 0x80000000, &index)) return 0; if (index != d->parent->csilength) { ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; } if (!ASN1BERDecExplicitTag(dd, 0x80000001, &dd2, &di2)) return 0; if (!ASN1BERDecPeekTag(dd2, &tag)) return 0; switch (tag) { case 0x80000000: val->identification.o = ASN1characterstring_identification_syntaxes_o; if (!ASN1BERDecExplicitTag(dd2, 0x80000000, &dd3, &di3)) return 0; if (!ASN1BERDecObjectIdentifier(dd3, 0x80000000, &val->identification.u.syntaxes.abstract)) return 0; if (!ASN1BERDecObjectIdentifier(dd3, 0x80000001, &val->identification.u.syntaxes.transfer)) return 0; if (!ASN1BERDecEndOfContents(dd2, dd3, di3)) return 0; break; case 0x80000001: val->identification.o = ASN1characterstring_identification_syntax_o; if (!ASN1BERDecObjectIdentifier(dd2, 0x80000001, &val->identification.u.syntax)) return 0; break; case 0x80000002: val->identification.o = ASN1characterstring_identification_presentation_context_id_o; if (!ASN1BERDecU32Val(dd2, 0x80000002, &val->identification.u.presentation_context_id)) return 0; break; case 0x80000003: val->identification.o = ASN1characterstring_identification_context_negotiation_o; if (!ASN1BERDecExplicitTag(dd2, 0x80000003, &dd3, &di3)) return 0; if (!ASN1BERDecU32Val(dd3, 0x80000000, &val-> identification.u.context_negotiation.presentation_context_id)) return 0; if (!ASN1BERDecObjectIdentifier(dd3, 0x80000001, &val->identification.u.context_negotiation.transfer_syntax)) return 0; if (!ASN1BERDecEndOfContents(dd2, dd3, di3)) return 0; break; case 0x80000004: val->identification.o = ASN1characterstring_identification_transfer_syntax_o; if (!ASN1BERDecObjectIdentifier(dd2, 0x80000004, &val->identification.u.transfer_syntax)) return 0; break; case 0x80000005: val->identification.o = ASN1characterstring_identification_fixed_o; if (!ASN1BERDecNull(dd2, 0x80000005)) return 0; break; default: ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; } if (!ASN1BERDecEndOfContents(dd, dd2, di2)) return 0; if (!ASN1DecAddCharacterStringIdentification(d->parent, &val->identification)) return 0; val->data_value.o = ASN1characterstring_data_value_encoded_o; if (!ASN1BERDecOctetString(dd, 0x80000003, &val->data_value.u.encoded)) return 0; if (!ASN1BERDecEndOfContents(dec, dd, di)) return 0; } else { /* primitive? CS-B encoded */ /* get length */ if (!ASN1BERDecLength(dec, &len, NULL)) return 0;
/* then copy value */ if (!len) { ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; } val->data_value.o = ASN1characterstring_data_value_encoded_o; val->data_value.u.encoded.length = len - 1; val->data_value.u.encoded.value = (ASN1octet_t *)DecMemAlloc(dec, len - 1); if (!val->data_value.u.encoded.value) { return 0; } index = *dec->pos++; CopyMemory(val->data_value.u.encoded.value, dec->pos, len - 1); identification = ASN1DecGetCharacterStringIdentification(d->parent, index); if (!identification) return 0; val->identification.o = identification->o; switch (identification->o) { case ASN1characterstring_identification_syntaxes_o: if (!ASN1DecDupObjectIdentifier(dec, &val->identification.u.syntaxes.abstract, &identification->u.syntaxes.abstract)) return 0; if (!ASN1DecDupObjectIdentifier(dec, &val->identification.u.syntaxes.transfer, &identification->u.syntaxes.transfer)) return 0; break; case ASN1characterstring_identification_syntax_o: if (!ASN1DecDupObjectIdentifier(dec, &val->identification.u.syntax, &identification->u.syntax)) return 0; break; case ASN1characterstring_identification_presentation_context_id_o: val->identification.u.presentation_context_id = identification->u.presentation_context_id; break; case ASN1characterstring_identification_context_negotiation_o: val->identification.u.context_negotiation.presentation_context_id = identification->u.context_negotiation.presentation_context_id; if (!ASN1DecDupObjectIdentifier(dec, &val->identification.u.context_negotiation.transfer_syntax, &identification->u.context_negotiation.transfer_syntax)) return 0; break; case ASN1characterstring_identification_transfer_syntax_o: if (!ASN1DecDupObjectIdentifier(dec, &val->identification.u.transfer_syntax, &identification->u.transfer_syntax)) return 0; break; case ASN1characterstring_identification_fixed_o: break; } } return 1; } #endif // ENABLE_GENERALIZED_CHAR_STR
#ifdef ENABLE_DOUBLE
/* decode real value */ int ASN1BERDecDouble(ASN1decoding_t dec, ASN1uint32_t tag, double *val) { ASN1uint32_t head; ASN1int32_t exponent; ASN1uint32_t baselog2; ASN1uint32_t len; ASN1uint32_t i; ASN1octet_t *p, *q; double v; char buf[256], *b;
/* skip tag */ if (!ASN1BERDecTag(dec, tag, NULL)) return 0;
/* get length */ if (!ASN1BERDecLength(dec, &len, NULL)) return 0;
/* null length is 0.0 */ if (!len) { *val = 0.0; } else { p = q = dec->pos; dec->pos += len; head = *p++;
/* binary encoding? */ if (head & 0x80) { /* get base */ switch (head & 0x30) { case 0: /* base 2 */ baselog2 = 1; break; case 0x10: /* base 8 */ baselog2 = 3; break; case 0x20: /* base 16 */ baselog2 = 4; break; default: ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; }
/* get exponent */ switch (head & 0x03) { case 0: /* 8 bit exponent */ exponent = (ASN1int8_t)*p++; break; case 1: /* 16 bit exponent */ exponent = (ASN1int16_t)((*p << 8) | p[1]); p += 2; break; case 2: /* 24 bit exponent */ exponent = ((*p << 16) | (p[1] << 8) | p[2]); if (exponent & 0x800000) exponent -= 0x1000000; break; default: /* variable length exponent */ exponent = (p[1] & 0x80) ? -1 : 0; for (i = 1; i <= *p; i++) exponent = (exponent << 8) | p[i]; p += *p + 1; break; }
/* calculate remaining length */ len -= (ASN1uint32_t) (p - q);
/* get mantissa */ v = 0.0; for (i = 0; i < len; i++) v = v * 256.0 + *p++;
/* scale mantissa */ switch (head & 0x0c) { case 0x04: /* scaling factor 1 */ v *= 2.0; break; case 0x08: /* scaling factor 2 */ v *= 4.0; break; case 0x0c: /* scaling factor 3 */ v *= 8.0; break; }
/* check sign */ if (head & 0x40) v = -v;
/* calculate value */ *val = ldexp(v, exponent * baselog2); } else /* special real values? */ if (head & 0x40) { switch (head) { case 0x40: /* PLUS-INFINITY */ *val = ASN1double_pinf(); break; case 0x41: /* MINUS-INFINITY */ *val = ASN1double_minf(); break; default: ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; } } /* decimal encoding */ else { CopyMemory(buf, p, len - 1); buf[len - 1] = 0; b = strchr(buf, ','); if (b) *b = '.'; *val = strtod((char *)buf, &b); if (*b) { ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; } } } return 1; } #endif // ENABLE_DOUBLE
#ifdef ENABLE_REAL
int ASN1BERDecReal(ASN1decoding_t dec, ASN1uint32_t tag, ASN1real_t *val) { ASN1uint32_t head; ASN1int32_t ex; // ASN1intx_t exponent;
ASN1uint32_t baselog2; ASN1uint32_t len; ASN1uint32_t i; ASN1octet_t *p, *q; double v; ASN1intx_t help;
if (!ASN1BERDecTag(dec, tag, NULL)) return 0; if (!ASN1BERDecLength(dec, &len, NULL)) return 0;
// *val = 0.0;
DecAssert(dec, 0 == (int) eReal_Normal); ZeroMemory(val, sizeof(*val)); if (len) { p = q = dec->pos; dec->pos += len; head = *p++;
/* binary encoding? */ if (head & 0x80) { val->type = eReal_Normal;
/* get base */ switch (head & 0x30) { case 0: /* base 2 */ baselog2 = 1; break; case 0x10: /* base 8 */ baselog2 = 3; break; case 0x20: /* base 16 */ baselog2 = 4; break; default: ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; }
/* get exponent */ switch (head & 0x03) { case 0: /* 8 bit exponent */ ex = (ASN1int8_t)*p++; ASN1intx_setint32(&val->exponent, ex); break; case 1: /* 16 bit exponent */ ex = (ASN1int16_t)((*p << 8) | p[1]); p += 2; // ASN1intx_setint32_t(&exponent, ex);
ASN1intx_setint32(&val->exponent, ex); break; case 2: /* 24 bit exponent */ ex = ((*p << 16) | (p[1] << 8) | p[2]); if (ex & 0x800000) ex -= 0x1000000; // ASN1intx_setint32_t(&exponent, ex);
ASN1intx_setint32(&val->exponent, ex); break; default: /* variable length exponent */ val->exponent.length = *p; val->exponent.value = (ASN1octet_t *)DecMemAlloc(dec, *p); if (!val->exponent.value) { return 0; } CopyMemory(val->exponent.value, p + 1, *p); p += *p + 1; break; }
/* calculate remaining length */ len -= (p - q); if (!len) { ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; }
/* get mantissa */ val->mantissa.length = (*p & 0x80) ? len + 1 : len; val->mantissa.value = (ASN1octet_t *)DecMemAlloc(dec, val->mantissa.length); if (!val->mantissa.value) { return 0; } val->mantissa.value[0] = 0; CopyMemory(val->mantissa.value + val->mantissa.length - len, p, len);
/* scale mantissa */ switch (head & 0x0c) { case 0x04: /* scaling factor 1 */ ASN1intx_muloctet(&help, &val->mantissa, 2); ASN1intx_free(&val->mantissa); val->mantissa = help; break; case 0x08: /* scaling factor 2 */ ASN1intx_muloctet(&help, &val->mantissa, 4); ASN1intx_free(&val->mantissa); val->mantissa = help; break; case 0x0c: /* scaling factor 3 */ ASN1intx_muloctet(&help, &val->mantissa, 8); ASN1intx_free(&val->mantissa); val->mantissa = help; break; }
/* check sign */ if (head & 0x40) { ASN1intx_neg(&help, &val->mantissa); ASN1intx_free(&val->mantissa); val->mantissa = help; } } else /* special real values? */ if (head & 0x40) { switch (head) { case 0x40: /* PLUS-INFINITY */ val->type = eReal_PlusInfinity; break; case 0x41: /* MINUS-INFINITY */ val->type = eReal_MinusInfinity; break; default: ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; } } /* decimal encoding */ else { char *b; char buf[256];
DecAssert(dec, (head & 0xc0) == 0xc0); CopyMemory(buf, p, len - 1); buf[len - 1] = 0; ex = 0; b = strchr(buf, ','); if (b) { // move the decimal point to the right
ex -= lstrlenA(b+1); lstrcpyA(b, b+1); } // skip leading zeros
for (b = &buf[0]; '0' == *b; b++) ; val->type = eReal_Normal; val->base = 10; ASN1intx_setint32(&val->exponent, ex); /*XXX*/ // missing code here!!!
// need to set val->mantissa through the decimal digits string
DecAssert(dec, 0); return 0; } } return 1; } #endif // ENABLE_REAL
#ifdef ENABLE_EMBEDDED_PDV
/* decode embedded pdv value */ int ASN1BERDecEmbeddedPdv(ASN1decoding_t dec, ASN1uint32_t tag, ASN1embeddedpdv_t *val) { ASN1INTERNdecoding_t d = (ASN1INTERNdecoding_t) dec; ASN1uint32_t constructed, len, infinite; ASN1uint32_t index; ASN1embeddedpdv_identification_t *identification; ASN1decoding_t dd, dd2, dd3; ASN1octet_t *di, *di2, *di3;
/* skip tag */ if (!ASN1BERDecTag(dec, tag, &constructed)) return 0;
if (constructed) { /* constructed? EP-A encoded: */ /* get length */ if (!ASN1BERDecLength(dec, &len, &infinite)) return 0;
/* then start decoding of constructed value */ if (! _BERDecConstructed(dec, len, infinite, &dd, &di)) return 0; if (!ASN1BERDecU32Val(dd, 0x80000000, &index)) return 0; if (index != d->parent->epilength) { ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; } if (!ASN1BERDecExplicitTag(dd, 0x80000001, &dd2, &di2)) return 0; if (!ASN1BERDecPeekTag(dd2, &tag)) return 0; switch (tag) { case 0x80000000: val->identification.o = ASN1embeddedpdv_identification_syntaxes_o; if (!ASN1BERDecExplicitTag(dd2, 0x80000000, &dd3, &di3)) return 0; if (!ASN1BERDecObjectIdentifier(dd3, 0x80000000, &val->identification.u.syntaxes.abstract)) return 0; if (!ASN1BERDecObjectIdentifier(dd3, 0x80000001, &val->identification.u.syntaxes.transfer)) return 0; if (!ASN1BERDecEndOfContents(dd2, dd3, di3)) return 0; break; case 0x80000001: val->identification.o = ASN1embeddedpdv_identification_syntax_o; if (!ASN1BERDecObjectIdentifier(dd2, 0x80000001, &val->identification.u.syntax)) return 0; break; case 0x80000002: val->identification.o = ASN1embeddedpdv_identification_presentation_context_id_o; if (!ASN1BERDecU32Val(dd2, 0x80000002, &val->identification.u.presentation_context_id)) return 0; break; case 0x80000003: val->identification.o = ASN1embeddedpdv_identification_context_negotiation_o; if (!ASN1BERDecExplicitTag(dd2, 0x80000003, &dd3, &di3)) return 0; if (!ASN1BERDecU32Val(dd3, 0x80000000, &val-> identification.u.context_negotiation.presentation_context_id)) return 0; if (!ASN1BERDecObjectIdentifier(dd3, 0x80000001, &val->identification.u.context_negotiation.transfer_syntax)) return 0; if (!ASN1BERDecEndOfContents(dd2, dd3, di3)) return 0; break; case 0x80000004: val->identification.o = ASN1embeddedpdv_identification_transfer_syntax_o; if (!ASN1BERDecObjectIdentifier(dd2, 0x80000004, &val->identification.u.transfer_syntax)) return 0; break; case 0x80000005: val->identification.o = ASN1embeddedpdv_identification_fixed_o; if (!ASN1BERDecNull(dd2, 0x80000005)) return 0; break; default: ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; } if (!ASN1BERDecEndOfContents(dd, dd2, di2)) return 0; if (!ASN1DecAddEmbeddedPdvIdentification(d->parent, &val->identification)) return 0; val->data_value.o = ASN1embeddedpdv_data_value_encoded_o; if (!ASN1BERDecBitString(dd, 0x80000003, &val->data_value.u.encoded)) return 0; if (!ASN1BERDecEndOfContents(dec, dd, di)) return 0; } else { /* primitive? EP-B encoded: */ if (!ASN1BERDecLength(dec, &len, NULL)) return 0;
/* then copy value */ if (!len) { ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; } val->data_value.o = ASN1embeddedpdv_data_value_encoded_o; val->data_value.u.encoded.length = 8 * (len - 1); val->data_value.u.encoded.value = (ASN1octet_t *)DecMemAlloc(dec, len - 1); if (!val->data_value.u.encoded.value) { return 0; } index = *dec->pos++; CopyMemory(val->data_value.u.encoded.value, dec->pos, len - 1); identification = ASN1DecGetEmbeddedPdvIdentification(d->parent, index); if (!identification) return 0; val->identification.o = identification->o; switch (identification->o) { case ASN1embeddedpdv_identification_syntaxes_o: if (!ASN1DecDupObjectIdentifier(dec, &val->identification.u.syntaxes.abstract, &identification->u.syntaxes.abstract)) return 0; if (!ASN1DecDupObjectIdentifier(dec, &val->identification.u.syntaxes.transfer, &identification->u.syntaxes.transfer)) return 0; break; case ASN1embeddedpdv_identification_syntax_o: if (!ASN1DecDupObjectIdentifier(dec, &val->identification.u.syntax, &identification->u.syntax)) return 0; break; case ASN1embeddedpdv_identification_presentation_context_id_o: val->identification.u.presentation_context_id = identification->u.presentation_context_id; break; case ASN1embeddedpdv_identification_context_negotiation_o: val->identification.u.context_negotiation.presentation_context_id = identification->u.context_negotiation.presentation_context_id; if (!ASN1DecDupObjectIdentifier(dec, &val->identification.u.context_negotiation.transfer_syntax, &identification->u.context_negotiation.transfer_syntax)) return 0; break; case ASN1embeddedpdv_identification_transfer_syntax_o: if (!ASN1DecDupObjectIdentifier(dec, &val->identification.u.transfer_syntax, &identification->u.transfer_syntax)) return 0; break; case ASN1embeddedpdv_identification_fixed_o: break; } } return 1; } #endif // ENABLE_EMBEDDED_PDV
#ifdef ENABLE_EXTERNAL
/* decode external value */ int ASN1BERDecExternal(ASN1decoding_t dec, ASN1uint32_t tag, ASN1external_t *val) { ASN1decoding_t dd; ASN1octet_t *di; ASN1objectidentifier_t id; ASN1octetstring_t os;
/* decode explicit tag */ if (!ASN1BERDecExplicitTag(dec, tag | 0x20000000, &dd, &di)) return 0;
/* peek tag of choice alternative */ if (!ASN1BERDecPeekTag(dd, &tag)) return 0;
/* decode alternative */ if (tag == 0x6) { if (!ASN1BERDecObjectIdentifier(dd, 0x6, &id)) return 0; if (!ASN1BERDecPeekTag(dd, &tag)) return 0; if (tag == 0x2) { val->identification.o = ASN1external_identification_context_negotiation_o; val->identification.u.context_negotiation.transfer_syntax = id; if (!ASN1BERDecU32Val(dd, 0x2, &val-> identification.u.context_negotiation.presentation_context_id)) return 0; if (!ASN1BERDecPeekTag(dd, &tag)) return 0; } else { val->identification.o = ASN1external_identification_syntax_o; val->identification.u.syntax = id; } } else if (tag == 0x2) { val->identification.o = ASN1external_identification_presentation_context_id_o; if (!ASN1BERDecU32Val(dd, 0x2, &val->identification.u.presentation_context_id)) return 0; if (!ASN1BERDecPeekTag(dd, &tag)) return 0; } else { ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; }
/* decode optional data value descriptor if present */ if (tag == 0x7) { if (!ASN1BERDecZeroCharString(dd, 0x7, &val->data_value_descriptor)) return 0; if (!ASN1BERDecPeekTag(dd, &tag)) return 0; } else { val->data_value_descriptor = NULL; }
/* decode data value alternative */ switch (tag) { case 0: val->data_value.o = ASN1external_data_value_notation_o; if (!ASN1BERDecOpenType(dd, &val->data_value.u.notation)) return 0; break; case 1: val->data_value.o = ASN1external_data_value_encoded_o; if (!ASN1BERDecOctetString(dd, 0x4, &os)) return 0; val->data_value.u.encoded.value = os.value; val->data_value.u.encoded.length = os.length * 8; break; case 2: val->data_value.o = ASN1external_data_value_encoded_o; if (!ASN1BERDecBitString(dd, 0x3, &val->data_value.u.encoded)) return 0; break; default: ASN1DecSetError(dec, ASN1_ERR_CORRUPT); return 0; }
/* end of constructed (explicit tagged) value */ if (!ASN1BERDecEndOfContents(dec, dd, di)) return 0;
return 1; } #endif // ENABLE_EXTERNAL
/* decode generalized time value */ int ASN1BERDecGeneralizedTime(ASN1decoding_t dec, ASN1uint32_t tag, ASN1generalizedtime_t *val) { ASN1ztcharstring_t time; if (ASN1BERDecZeroCharString(dec, tag, &time)) { int rc = ASN1string2generalizedtime(val, time); DecMemFree(dec, time); if (rc) { return 1; } ASN1DecSetError(dec, ASN1_ERR_CORRUPT); } return 0; }
/* decode multibyte string value */ int ASN1BERDecZeroMultibyteString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztcharstring_t *val) { return ASN1BERDecZeroCharString(dec, tag, val); }
int ASN1BERDecMultibyteString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1charstring_t *val) { return ASN1BERDecCharString(dec, tag, val); }
/* decode null value */ int ASN1BERDecNull(ASN1decoding_t dec, ASN1uint32_t tag) { ASN1uint32_t len; if (ASN1BERDecTag(dec, tag, NULL)) { if (ASN1BERDecLength(dec, &len, NULL)) { if (! len) { return 1; } ASN1DecSetError(dec, ASN1_ERR_CORRUPT); } } return 0; }
/* decode object identifier value */ int ASN1BERDecObjectIdentifier(ASN1decoding_t dec, ASN1uint32_t tag, ASN1objectidentifier_t *val) { if (ASN1BERDecTag(dec, tag, NULL)) { ASN1uint32_t len, i, v; ASN1octet_t *data, *p; ASN1uint32_t nelem; ASN1objectidentifier_t q;
if (ASN1BERDecLength(dec, &len, NULL)) { data = dec->pos; dec->pos += len; nelem = 1; for (i = 0, p = data; i < len; i++, p++) { if (!(*p & 0x80)) nelem++; } *val = q = DecAllocObjectIdentifier(dec, nelem); if (q) { v = 0; for (i = 0, p = data; i < len; i++, p++) { v = (v << 7) | (*p & 0x7f); if (!(*p & 0x80)) { if (q == *val) { // first id
q->value = v / 40; if (q->value > 2) q->value = 2; q->next->value = v - 40 * q->value; q = q->next->next; } else { q->value = v; q = q->next; } v = 0; } } return 1; } } } return 0; }
/* decode object identifier value */ int ASN1BERDecObjectIdentifier2(ASN1decoding_t dec, ASN1uint32_t tag, ASN1objectidentifier2_t *val) { if (ASN1BERDecTag(dec, tag, NULL)) { ASN1uint32_t len, i, v; ASN1octet_t *data, *p; ASN1objectidentifier_t q;
if (ASN1BERDecLength(dec, &len, NULL)) { if (len <= 16) // lonchanc: hard-coded value 16 to be consistent with ASN1objectidentifier2_t
{ data = dec->pos; dec->pos += len; val->count = 0; v = 0; for (i = 0, p = data; i < len; i++, p++) { v = (v << 7) | (*p & 0x7f); if (!(*p & 0x80)) { if (! val->count) { // first id
val->value[0] = v / 40; if (val->value[0] > 2) val->value[0] = 2; val->value[1] = v - 40 * val->value[0]; val->count = 2; } else { val->value[val->count++] = v; } v = 0; } } return 1; } else { ASN1DecSetError(dec, ASN1_ERR_LARGE); } } } return 0; }
/* decode integer into signed 8 bit value */ int ASN1BERDecS8Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1int8_t *val) { /* skip tag */ if (ASN1BERDecTag(dec, tag, NULL)) { ASN1uint32_t len; /* get length */ if (ASN1BERDecLength(dec, &len, NULL)) { /* get value */ if (1 == len) { *val = *dec->pos++; return 1; } ASN1DecSetError(dec, (len < 1) ? ASN1_ERR_CORRUPT : ASN1_ERR_LARGE); } } return 0; }
/* decode integer into signed 16 bit value */ int ASN1BERDecS16Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1int16_t *val) { /* skip tag */ if (ASN1BERDecTag(dec, tag, NULL)) { ASN1uint32_t len; /* get length */ if (ASN1BERDecLength(dec, &len, NULL)) { /* get value */ switch (len) { case 1: *val = *dec->pos++; break; case 2: *val = (*dec->pos << 8) | dec->pos[1]; dec->pos += 2; break; default: ASN1DecSetError(dec, (len < 1) ? ASN1_ERR_CORRUPT : ASN1_ERR_LARGE); return 0; } return 1; } } return 0; }
const ASN1int32_t c_nSignMask[] = { 0xFFFFFF00, 0xFFFF0000, 0xFF000000, 0 };
/* decode integer into signed 32 bit value */ int ASN1BERDecS32Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1int32_t *val) { /* skip tag */ if (ASN1BERDecTag(dec, tag, NULL)) { ASN1uint32_t len; /* get length */ if (ASN1BERDecLength(dec, &len, NULL)) { int fSigned = 0x80 & *dec->pos;
/* get value */ switch (len) { case 1: *val = *dec->pos++; break; case 2: *val = (*dec->pos << 8) | dec->pos[1]; dec->pos += 2; break; case 3: *val = (*dec->pos << 16) | (dec->pos[1] << 8) | dec->pos[2]; dec->pos += 3; break; case 4: *val = (*dec->pos << 24) | (dec->pos[1] << 16) | (dec->pos[2] << 8) | dec->pos[3]; dec->pos += 4; break; default: ASN1DecSetError(dec, (len < 1) ? ASN1_ERR_CORRUPT : ASN1_ERR_LARGE); return 0; } if (fSigned) { *val |= c_nSignMask[len-1]; } return 1; } } return 0; }
/* decode integer into intx value */ int ASN1BERDecSXVal(ASN1decoding_t dec, ASN1uint32_t tag, ASN1intx_t *val) { /* skip tag */ if (ASN1BERDecTag(dec, tag, NULL)) { ASN1uint32_t len; /* get length */ if (ASN1BERDecLength(dec, &len, NULL)) { /* get value */ if (len >= 1) { val->length = len; val->value = (ASN1octet_t *)DecMemAlloc(dec, len); if (val->value) { CopyMemory(val->value, dec->pos, len); dec->pos += len; return 1; } } else { ASN1DecSetError(dec, ASN1_ERR_CORRUPT); } } } return 0; }
/* decode integer into unsigned 8 bit value */ int ASN1BERDecU8Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1uint8_t *val) { /* skip tag */ if (ASN1BERDecTag(dec, tag, NULL)) { ASN1uint32_t len; /* get length */ if (ASN1BERDecLength(dec, &len, NULL)) { /* get value */ switch (len) { case 1: *val = *dec->pos++; return 1; case 2: if (0 == *dec->pos) { *val = dec->pos[1]; dec->pos += 2; return 1; } // intentionally fall through
default: ASN1DecSetError(dec, (len < 1) ? ASN1_ERR_CORRUPT : ASN1_ERR_LARGE); break; } } } return 0; }
/* decode integer into unsigned 16 bit value */ int ASN1BERDecU16Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1uint16_t *val) { /* skip tag */ if (ASN1BERDecTag(dec, tag, NULL)) { ASN1uint32_t len; /* get length */ if (ASN1BERDecLength(dec, &len, NULL)) { /* get value */ switch (len) { case 1: *val = *dec->pos++; return 1; case 2: *val = (*dec->pos << 8) | dec->pos[1]; dec->pos += 2; return 1; case 3: if (0 == *dec->pos) { *val = (dec->pos[1] << 8) | dec->pos[2]; dec->pos += 3; return 1; } // intentionally fall through
default: ASN1DecSetError(dec, (len < 1) ? ASN1_ERR_CORRUPT : ASN1_ERR_LARGE); break; } } } return 0; }
/* decode utc time value */ int ASN1BERDecUTCTime(ASN1decoding_t dec, ASN1uint32_t tag, ASN1utctime_t *val) { ASN1ztcharstring_t time; if (ASN1BERDecZeroCharString(dec, tag, &time)) { int rc = ASN1string2utctime(val, time); DecMemFree(dec, time); if (rc) { return 1; } ASN1DecSetError(dec, ASN1_ERR_CORRUPT); } return 0; }
/* decode zero terminated string value */ int ASN1BERDecZeroCharString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztcharstring_t *val) { ASN1uint32_t constructed, len, infinite; ASN1ztcharstring_t c; ASN1decoding_t dd; ASN1octet_t *di; ASN1uint32_t lv, lc;
/* skip tag */ if (ASN1BERDecTag(dec, tag, &constructed)) { /* get length */ if (ASN1BERDecLength(dec, &len, &infinite)) { if (constructed) { /* constructed? then start decoding of constructed value */ *val = NULL; if (_BERDecConstructed(dec, len, infinite, &dd, &di)) { while (ASN1BERDecNotEndOfContents(dd, di)) { if (ASN1BERDecZeroCharString(dd, 0x4, &c)) { lv = My_lstrlenA(*val); lc = My_lstrlenA(c); if (lc) { /* resize value */ *val = (char *)DecMemReAlloc(dd, *val, lv + lc + 1); if (*val) { /* concat strings */ CopyMemory(*val + lv, c, lc + 1);
/* free unused string */ DecMemFree(dec, c); } else { return 0; } } } else { return 0; } } // while
return ASN1BERDecEndOfContents(dec, dd, di); } } else { /* primitive? then copy value */ *val = (char *)DecMemAlloc(dec, len + 1); if (*val) { CopyMemory(*val, dec->pos, len); (*val)[len] = 0; dec->pos += len; return 1; } } } } return 0; }
/* decode zero terminated 16 bit string value */ int ASN1BERDecZeroChar16String(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztchar16string_t *val) { ASN1uint32_t constructed, len, infinite; ASN1ztchar16string_t c; ASN1decoding_t dd; ASN1octet_t *di; ASN1uint32_t i; ASN1uint32_t lv, lc;
/* skip tag */ if (ASN1BERDecTag(dec, tag, &constructed)) { /* get length */ if (ASN1BERDecLength(dec, &len, &infinite)) { if (constructed) { /* constructed? then start decoding of constructed value */ *val = NULL; if (_BERDecConstructed(dec, len, infinite, &dd, &di)) { while (ASN1BERDecNotEndOfContents(dd, di)) { if (ASN1BERDecZeroChar16String(dd, 0x4, &c)) { lv = ASN1str16len(*val); lc = ASN1str16len(c); if (lc) { /* resize value */ *val = (ASN1char16_t *)DecMemReAlloc(dd, *val, (lv + lc + 1) * sizeof(ASN1char16_t)); if (*val) { /* concat strings */ CopyMemory(*val + lv, c, (lc + 1) * sizeof(ASN1char16_t));
/* free unused string */ DecMemFree(dec, c); } else { return 0; } } } else { return 0; } } // while
return ASN1BERDecEndOfContents(dec, dd, di); } } else { /* primitive? then copy value */ *val = (ASN1char16_t *)DecMemAlloc(dec, (len + 1) * sizeof(ASN1char16_t)); if (*val) { for (i = 0; i < len; i++) { (*val)[i] = (*dec->pos << 8) | dec->pos[1]; dec->pos += 2; } (*val)[len] = 0; return 1; } } } } return 0; }
/* decode zero terminated 32 bit string value */ int ASN1BERDecZeroChar32String(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztchar32string_t *val) { ASN1uint32_t constructed, len, infinite; ASN1ztchar32string_t c; ASN1decoding_t dd; ASN1octet_t *di; ASN1uint32_t i; ASN1uint32_t lv, lc;
/* skip tag */ if (ASN1BERDecTag(dec, tag, &constructed)) { /* get length */ if (ASN1BERDecLength(dec, &len, &infinite)) { if (constructed) { /* constructed? then start decoding of constructed value */ *val = (ASN1char32_t *)DecMemAlloc(dec, sizeof(ASN1char32_t)); if (*val) { **val = 0; if (_BERDecConstructed(dec, len, infinite, &dd, &di)) { while (ASN1BERDecNotEndOfContents(dd, di)) { if (ASN1BERDecZeroChar32String(dd, 0x4, &c)) { lv = ASN1str32len(*val); lc = ASN1str32len(c); if (lc) { /* resize value */ *val = (ASN1char32_t *)DecMemReAlloc(dd, *val, (lv + lc + 1) * sizeof(ASN1char32_t)); if (*val) { /* concat strings */ CopyMemory(*val + lv, c, (lc + 1) * sizeof(ASN1char32_t));
/* free unused string */ DecMemFree(dec, c); } } } else { return 0; } } return ASN1BERDecEndOfContents(dec, dd, di); } } } else { /* primitive? then copy value */ *val = (ASN1char32_t *)DecMemAlloc(dec, (len + 1) * sizeof(ASN1char32_t)); if (*val) { for (i = 0; i < len; i++) { (*val)[i] = (*dec->pos << 24) | (dec->pos[1] << 16) | (dec->pos[2] << 8) | dec->pos[3];; dec->pos += 4; } (*val)[len] = 0; return 1; } } } } return 0; }
/* skip a value */ int ASN1BERDecSkip(ASN1decoding_t dec) { ASN1uint32_t tag; ASN1uint32_t constructed, len, infinite; ASN1decoding_t dd; ASN1octet_t *di;
/* set warning flag */ ASN1DecSetError(dec, ASN1_WRN_EXTENDED);
/* read tag */ if (ASN1BERDecPeekTag(dec, &tag)) { if (ASN1BERDecTag(dec, tag, &constructed)) { if (constructed) { /* constructed? then get length */ if (ASN1BERDecLength(dec, &len, &infinite)) { if (!infinite) { /* skip value */ dec->pos += len; // remove the above warning set previously
ASN1DecSetError(dec, ASN1_SUCCESS); return 1; }
/* start skipping of constructed value */ if (_BERDecConstructed(dec, len, infinite, &dd, &di)) { while (ASN1BERDecNotEndOfContents(dd, di)) { if (ASN1BERDecSkip(dd)) { continue; } return 0; } if (ASN1BERDecEndOfContents(dec, dd, di)) { // remove the above warning set previously
ASN1DecSetError(dec, ASN1_SUCCESS); return 1; } return 0; } } } else { /* primitive? then get length */ if (ASN1BERDecLength(dec, &len, NULL)) { /* skip value */ dec->pos += len; // remove the above warning set previously
ASN1DecSetError(dec, ASN1_SUCCESS); return 1; } } } } return 0; }
/* decode an open type value */ int _BERDecOpenType(ASN1decoding_t dec, ASN1open_t *val, ASN1uint32_t fNoCopy) { ASN1uint32_t tag; ASN1uint32_t constructed, len, infinite; ASN1decoding_t dd; ASN1octet_t *di; ASN1octet_t *p;
p = dec->pos;
/* skip tag */ if (ASN1BERDecPeekTag(dec, &tag)) { if (ASN1BERDecTag(dec, tag, &constructed)) { if (constructed) { /* constructed? then get length */ if (ASN1BERDecLength(dec, &len, &infinite)) { if (!infinite) { /* skip value */ dec->pos += len; goto MakeCopy; }
/* start decoding of constructed value */ if (_BERDecConstructed(dec, len, infinite, &dd, &di)) { while (ASN1BERDecNotEndOfContents(dd, di)) { if (ASN1BERDecSkip(dd)) { continue; } return 0; } if (ASN1BERDecEndOfContents(dec, dd, di)) { goto MakeCopy; } } } return 0; } else { /* primitive? then get length */ if (ASN1BERDecLength(dec, &len, NULL)) { /* skip value */ dec->pos += len; } else { return 0; } }
MakeCopy:
// clean up unused fields
// val->decoded = NULL;
// val->userdata = NULL;
/* copy skipped value */ val->length = (ASN1uint32_t) (dec->pos - p); if (fNoCopy) { val->encoded = p; return 1; } else { val->encoded = (ASN1octet_t *)DecMemAlloc(dec, val->length); if (val->encoded) { CopyMemory(val->encoded, p, val->length); return 1; } } } } return 0; }
/* decode an open type value, making a copy */ int ASN1BERDecOpenType(ASN1decoding_t dec, ASN1open_t *val) { return _BERDecOpenType(dec, val, FALSE); }
/* decode an open type value, no copy */ int ASN1BERDecOpenType2(ASN1decoding_t dec, ASN1open_t *val) { return _BERDecOpenType(dec, val, TRUE); }
/* finish decoding */ int ASN1BERDecFlush(ASN1decoding_t dec) { /* calculate length */ dec->len = (ASN1uint32_t) (dec->pos - dec->buf);
/* set WRN_NOEOD if data left */ if (dec->len >= dec->size) { DecAssert(dec, dec->len == dec->size); return 1; } ASN1DecSetError(dec, ASN1_WRN_NOEOD); return 1; }
#endif // ENABLE_BER
|