asn1-private.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Embedded Linux library
  3. *
  4. * Copyright (C) 2017 Intel Corporation. All rights reserved.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #define ASN1_ID(class, pc, tag) (((class) << 6) | ((pc) << 5) | (tag))
  21. #define ASN1_CLASS_UNIVERSAL 0
  22. #define ASN1_CLASS_CONTEXT 2
  23. #define ASN1_ID_SEQUENCE ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x10)
  24. #define ASN1_ID_SET ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x11)
  25. #define ASN1_ID_BOOLEAN ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x01)
  26. #define ASN1_ID_INTEGER ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x02)
  27. #define ASN1_ID_BIT_STRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x03)
  28. #define ASN1_ID_OCTET_STRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x04)
  29. #define ASN1_ID_NULL ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x05)
  30. #define ASN1_ID_OID ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x06)
  31. #define ASN1_ID_UTF8STRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x0c)
  32. #define ASN1_ID_PRINTABLESTRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x13)
  33. #define ASN1_ID_IA5STRING ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x16)
  34. struct asn1_oid {
  35. uint8_t asn1_len;
  36. uint8_t asn1[11];
  37. };
  38. #define asn1_oid_eq(oid1, oid2_len, oid2_string) \
  39. ((oid1)->asn1_len == (oid2_len) && \
  40. !memcmp((oid1)->asn1, (oid2_string), (oid2_len)))
  41. #if __STDC_VERSION__ <= 199409L
  42. #define inline __inline__
  43. #endif
  44. static inline int asn1_parse_definite_length(const uint8_t **buf,
  45. size_t *len)
  46. {
  47. int n;
  48. size_t result = 0;
  49. /* Decrease the buffer length left */
  50. if ((*len)-- < 1)
  51. return -1;
  52. /*
  53. * If short form length, move the pointer to start of data and
  54. * return the data length.
  55. */
  56. if (!(**buf & 0x80))
  57. return *(*buf)++;
  58. n = *(*buf)++ & 0x7f;
  59. if ((size_t) n > *len)
  60. return -1;
  61. *len -= n;
  62. while (n--)
  63. result = (result << 8) | *(*buf)++;
  64. return result;
  65. }
  66. static inline void asn1_write_definite_length(uint8_t **buf, size_t len)
  67. {
  68. int n;
  69. if (len < 0x80) {
  70. *(*buf)++ = len;
  71. return;
  72. }
  73. for (n = 1; len >> (n * 8); n++);
  74. *(*buf)++ = 0x80 | n;
  75. while (n--)
  76. *(*buf)++ = len >> (n * 8);
  77. }
  78. #define ASN1_CONTEXT_IMPLICIT(tag) (0x1000 | (tag))
  79. #define ASN1_CONTEXT_EXPLICIT(tag) (0x2000 | (tag))
  80. /*
  81. * Return the tag, length and value of the @index'th
  82. * non-context-specific-tagged element in a DER SEQUENCE or one who's
  83. * ASN1_CONTEXT_IMPLICIT(tag) matches @index or the inner element of
  84. * the one who's ASN1_CONTEXT_EXPLICIT(tag) matches @index.
  85. */
  86. static inline const uint8_t *asn1_der_find_elem(const uint8_t *buf,
  87. size_t len_in, int index,
  88. uint8_t *tag, size_t *len_out)
  89. {
  90. int n = 0;
  91. while (1) {
  92. int tlv_len;
  93. if (len_in < 2)
  94. return NULL;
  95. *tag = *buf++;
  96. len_in--;
  97. tlv_len = asn1_parse_definite_length((void *) &buf, &len_in);
  98. if (tlv_len < 0 || (size_t) tlv_len > len_in)
  99. return NULL;
  100. if (*tag >> 6 != ASN1_CLASS_CONTEXT) {
  101. if (n++ == index) {
  102. *len_out = tlv_len;
  103. return buf;
  104. }
  105. } else if ((*tag & 0x1f) == (index & 0xfff)) {
  106. /* Context-specific tag */
  107. if (index & 0x1000) { /* Implicit */
  108. *len_out = tlv_len;
  109. return buf;
  110. } else if (index & 0x2000) { /* Explicit */
  111. const uint8_t *outer = buf;
  112. int inner_len;
  113. if (!(*tag & 0x20)) /* Primitive */
  114. return NULL;
  115. if (tlv_len < 2)
  116. return NULL;
  117. *tag = *buf++;
  118. inner_len = asn1_parse_definite_length(
  119. (void *) &buf, &len_in);
  120. if (outer + tlv_len != buf + inner_len)
  121. return NULL;
  122. *len_out = inner_len;
  123. return buf;
  124. }
  125. }
  126. buf += tlv_len;
  127. len_in -= tlv_len;
  128. }
  129. }
  130. /* Return an element in a DER SEQUENCE structure by path */
  131. static inline const uint8_t *asn1_der_find_elem_by_path(const uint8_t *buf,
  132. size_t len_in, uint8_t tag,
  133. size_t *len_out, ...)
  134. {
  135. int index;
  136. va_list vl;
  137. va_start(vl, len_out);
  138. index = va_arg(vl, int);
  139. while (index != -1) {
  140. uint8_t elem_tag;
  141. uint8_t expect_tag;
  142. int prev_index = index;
  143. buf = asn1_der_find_elem(buf, len_in, index,
  144. &elem_tag, &len_in);
  145. if (!buf) {
  146. va_end(vl);
  147. return NULL;
  148. }
  149. index = va_arg(vl, int);
  150. if (prev_index & 0x1000)
  151. expect_tag = ASN1_ID(ASN1_CLASS_CONTEXT,
  152. index != -1 ? 1 :
  153. ((elem_tag >> 5) & 1),
  154. prev_index & 0xfff);
  155. else
  156. expect_tag = (index == -1) ? tag : ASN1_ID_SEQUENCE;
  157. if (elem_tag != expect_tag) {
  158. va_end(vl);
  159. return NULL;
  160. }
  161. }
  162. va_end(vl);
  163. *len_out = len_in;
  164. return buf;
  165. }