NativeEnumerated_oer.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
  3. * All rights reserved.
  4. * Redistribution and modifications are permitted subject to BSD license.
  5. */
  6. #ifndef ASN_DISABLE_OER_SUPPORT
  7. #include <asn_internal.h>
  8. #include <NativeEnumerated.h>
  9. #include <errno.h>
  10. static long
  11. asn__nativeenumerated_convert(const uint8_t *b, const uint8_t *end) {
  12. unsigned long value;
  13. /* Perform the sign initialization */
  14. /* Actually value = -(*b >> 7); gains nothing, yet unreadable! */
  15. if((*b >> 7)) {
  16. value = (unsigned long)(-1);
  17. } else {
  18. value = 0;
  19. }
  20. /* Conversion engine */
  21. for(; b < end; b++) {
  22. value = (value << 8) | *b;
  23. }
  24. return value;
  25. }
  26. asn_dec_rval_t
  27. NativeEnumerated_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
  28. const asn_TYPE_descriptor_t *td,
  29. const asn_oer_constraints_t *constraints,
  30. void **nint_ptr, const void *ptr, size_t size) {
  31. asn_dec_rval_t rval = {RC_OK, 0};
  32. long *native = (long *)*nint_ptr;
  33. const uint8_t *b = ptr;
  34. (void)opt_codec_ctx;
  35. (void)constraints;
  36. if(size < 1) {
  37. ASN__DECODE_STARVED;
  38. }
  39. if((*b & 0x80) == 0) {
  40. /*
  41. * X.696 (08/2015) #11.2 Short form for Enumerated.
  42. */
  43. if(!native) {
  44. native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
  45. if(!native) ASN__DECODE_FAILED;
  46. }
  47. *native = *b;
  48. rval.consumed = 1;
  49. } else {
  50. /*
  51. * X.696 (08/2015) #11.4 Long form for Enumerated.
  52. */
  53. size_t length = *b & 0x7f;
  54. const uint8_t *bend;
  55. long value;
  56. if(length < 1 || length > sizeof(*native)) {
  57. ASN__DECODE_FAILED;
  58. }
  59. if((1 + length) > size) {
  60. ASN__DECODE_STARVED;
  61. }
  62. b++;
  63. bend = b + length;
  64. value = asn__nativeenumerated_convert(b, bend);
  65. if(value < 0) {
  66. const asn_INTEGER_specifics_t *specs =
  67. (const asn_INTEGER_specifics_t *)td->specifics;
  68. if(specs && specs->field_unsigned) {
  69. ASN__DECODE_FAILED;
  70. }
  71. }
  72. if(!native) {
  73. native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
  74. if(!native) ASN__DECODE_FAILED;
  75. }
  76. *native = value;
  77. rval.consumed = (1 + length);
  78. }
  79. return rval;
  80. }
  81. /*
  82. * Encode as Canonical OER.
  83. */
  84. asn_enc_rval_t
  85. NativeEnumerated_encode_oer(const asn_TYPE_descriptor_t *td,
  86. const asn_oer_constraints_t *constraints,
  87. const void *sptr, asn_app_consume_bytes_f *cb,
  88. void *app_key) {
  89. asn_enc_rval_t er;
  90. long native;
  91. (void)constraints;
  92. if(!sptr) ASN__ENCODE_FAILED;
  93. native = *(const long *)sptr;
  94. if(native >= 0 && native <= 127) {
  95. /* #11.2 Short form */
  96. uint8_t b = native;
  97. er.encoded = 1;
  98. if(cb(&b, er.encoded, app_key) < 0) {
  99. ASN__ENCODE_FAILED;
  100. }
  101. ASN__ENCODED_OK(er);
  102. } else {
  103. /* #11.2 Long form */
  104. uint8_t buf[1 + sizeof(native)];
  105. uint8_t *b = &buf[sizeof(native)]; /* Last addressable */
  106. long final_pattern = -1 * (native < 0);
  107. for(;;) {
  108. *b-- = native;
  109. native >>= 8;
  110. if(native == final_pattern) {
  111. if(final_pattern) {
  112. if((b[1] & 0x80)) break;
  113. } else {
  114. if(!(b[1] & 0x80)) break;
  115. }
  116. }
  117. }
  118. *b = 0x80 | (&buf[sizeof(native)] - b);
  119. er.encoded = 1 + (&buf[sizeof(native)] - b);
  120. if(cb(b, er.encoded, app_key) < 0) {
  121. ASN__ENCODE_FAILED;
  122. }
  123. ASN__ENCODED_OK(er);
  124. }
  125. }
  126. #endif /* ASN_DISABLE_OER_SUPPORT */