You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

303 rivejä
7.3 KiB

  1. /* Copyright (c) 2014, Google Inc.
  2. *
  3. * Permission to use, copy, modify, and/or distribute this software for any
  4. * purpose with or without fee is hereby granted, provided that the above
  5. * copyright notice and this permission notice appear in all copies.
  6. *
  7. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. #include <openssl/buf.h>
  15. #include <openssl/mem.h>
  16. #include <openssl/bytestring.h>
  17. #include <assert.h>
  18. #include <string.h>
  19. void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
  20. cbs->data = data;
  21. cbs->len = len;
  22. }
  23. static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
  24. if (cbs->len < n) {
  25. return 0;
  26. }
  27. *p = cbs->data;
  28. cbs->data += n;
  29. cbs->len -= n;
  30. return 1;
  31. }
  32. int CBS_skip(CBS *cbs, size_t len) {
  33. const uint8_t *dummy;
  34. return cbs_get(cbs, &dummy, len);
  35. }
  36. const uint8_t *CBS_data(const CBS *cbs) {
  37. return cbs->data;
  38. }
  39. size_t CBS_len(const CBS *cbs) {
  40. return cbs->len;
  41. }
  42. int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
  43. if (*out_ptr != NULL) {
  44. OPENSSL_free(*out_ptr);
  45. *out_ptr = NULL;
  46. }
  47. *out_len = 0;
  48. if (cbs->len == 0) {
  49. return 1;
  50. }
  51. *out_ptr = BUF_memdup(cbs->data, cbs->len);
  52. if (*out_ptr == NULL) {
  53. return 0;
  54. }
  55. *out_len = cbs->len;
  56. return 1;
  57. }
  58. int CBS_strdup(const CBS *cbs, char **out_ptr) {
  59. if (*out_ptr != NULL) {
  60. OPENSSL_free(*out_ptr);
  61. }
  62. *out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
  63. return (*out_ptr != NULL);
  64. }
  65. int CBS_contains_zero_byte(const CBS *cbs) {
  66. return memchr(cbs->data, 0, cbs->len) != NULL;
  67. }
  68. int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
  69. if (len != cbs->len)
  70. return 0;
  71. return CRYPTO_memcmp(cbs->data, data, len) == 0;
  72. }
  73. static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
  74. uint32_t result = 0;
  75. size_t i;
  76. const uint8_t *data;
  77. if (!cbs_get(cbs, &data, len)) {
  78. return 0;
  79. }
  80. for (i = 0; i < len; i++) {
  81. result <<= 8;
  82. result |= data[i];
  83. }
  84. *out = result;
  85. return 1;
  86. }
  87. int CBS_get_u8(CBS *cbs, uint8_t *out) {
  88. const uint8_t *v;
  89. if (!cbs_get(cbs, &v, 1)) {
  90. return 0;
  91. }
  92. *out = *v;
  93. return 1;
  94. }
  95. int CBS_get_u16(CBS *cbs, uint16_t *out) {
  96. uint32_t v;
  97. if (!cbs_get_u(cbs, &v, 2)) {
  98. return 0;
  99. }
  100. *out = v;
  101. return 1;
  102. }
  103. int CBS_get_u24(CBS *cbs, uint32_t *out) {
  104. return cbs_get_u(cbs, out, 3);
  105. }
  106. int CBS_get_u32(CBS *cbs, uint32_t *out) {
  107. return cbs_get_u(cbs, out, 4);
  108. }
  109. int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
  110. const uint8_t *v;
  111. if (!cbs_get(cbs, &v, len)) {
  112. return 0;
  113. }
  114. CBS_init(out, v, len);
  115. return 1;
  116. }
  117. static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
  118. uint32_t len;
  119. if (!cbs_get_u(cbs, &len, len_len)) {
  120. return 0;
  121. }
  122. return CBS_get_bytes(cbs, out, len);
  123. }
  124. int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
  125. return cbs_get_length_prefixed(cbs, out, 1);
  126. }
  127. int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
  128. return cbs_get_length_prefixed(cbs, out, 2);
  129. }
  130. int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
  131. return cbs_get_length_prefixed(cbs, out, 3);
  132. }
  133. static int cbs_get_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
  134. size_t *out_header_len, unsigned depth,
  135. int *was_indefinite_len);
  136. /* cbs_get_asn1_indefinite_len sets |*out| to be a CBS that covers an
  137. * indefinite length element in |cbs| and advances |*in|. On entry, |cbs| will
  138. * not have had the tag and length byte removed. On exit, |*out| does not cover
  139. * the EOC element, but |*in| is skipped over it.
  140. *
  141. * The |depth| argument counts the number of times the code has recursed trying
  142. * to find an indefinite length. */
  143. static int cbs_get_asn1_indefinite_len(CBS *in, CBS *out, unsigned depth) {
  144. static const size_t kEOCLength = 2;
  145. size_t header_len;
  146. unsigned tag;
  147. int was_indefinite_len;
  148. CBS orig = *in, child;
  149. if (!CBS_skip(in, 2 /* tag plus 0x80 byte for indefinite len */)) {
  150. return 0;
  151. }
  152. for (;;) {
  153. if (!cbs_get_asn1_element(in, &child, &tag, &header_len, depth + 1,
  154. &was_indefinite_len)) {
  155. return 0;
  156. }
  157. if (!was_indefinite_len && CBS_len(&child) == kEOCLength &&
  158. header_len == kEOCLength && tag == 0) {
  159. break;
  160. }
  161. }
  162. return CBS_get_bytes(&orig, out, CBS_len(&orig) - CBS_len(in) - kEOCLength);
  163. }
  164. /* MAX_DEPTH the maximum number of levels of indefinite lengths that we'll
  165. * support. */
  166. #define MAX_DEPTH 64
  167. static int cbs_get_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
  168. size_t *out_header_len, unsigned depth,
  169. int *was_indefinite_len) {
  170. uint8_t tag, length_byte;
  171. CBS header = *cbs;
  172. if (!CBS_get_u8(&header, &tag) ||
  173. !CBS_get_u8(&header, &length_byte)) {
  174. return 0;
  175. }
  176. if ((tag & 0x1f) == 0x1f) {
  177. /* Long form tags are not supported. */
  178. return 0;
  179. }
  180. *out_tag = tag;
  181. if (was_indefinite_len) {
  182. *was_indefinite_len = 0;
  183. }
  184. size_t len;
  185. if ((length_byte & 0x80) == 0) {
  186. /* Short form length. */
  187. len = ((size_t) length_byte) + 2;
  188. *out_header_len = 2;
  189. } else {
  190. /* Long form length. */
  191. const size_t num_bytes = length_byte & 0x7f;
  192. uint32_t len32;
  193. if (depth < MAX_DEPTH && num_bytes == 0) {
  194. /* indefinite length */
  195. *out_header_len = 2;
  196. if (was_indefinite_len) {
  197. *was_indefinite_len = 1;
  198. }
  199. return cbs_get_asn1_indefinite_len(cbs, out, depth);
  200. }
  201. if (num_bytes == 0 || num_bytes > 4) {
  202. return 0;
  203. }
  204. if (!cbs_get_u(&header, &len32, num_bytes)) {
  205. return 0;
  206. }
  207. if (len32 < 128) {
  208. /* Length should have used short-form encoding. */
  209. return 0;
  210. }
  211. if ((len32 >> ((num_bytes-1)*8)) == 0) {
  212. /* Length should have been at least one byte shorter. */
  213. return 0;
  214. }
  215. len = len32;
  216. if (len + 2 + num_bytes < len) {
  217. /* Overflow. */
  218. return 0;
  219. }
  220. len += 2 + num_bytes;
  221. *out_header_len = 2 + num_bytes;
  222. }
  223. return CBS_get_bytes(cbs, out, len);
  224. }
  225. static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value, int ber,
  226. int skip_header) {
  227. size_t header_len;
  228. unsigned tag;
  229. CBS throwaway;
  230. if (out == NULL) {
  231. out = &throwaway;
  232. }
  233. if (!cbs_get_asn1_element(cbs, out, &tag, &header_len, ber ? 0 : MAX_DEPTH,
  234. NULL) ||
  235. tag != tag_value) {
  236. return 0;
  237. }
  238. if (skip_header && !CBS_skip(out, header_len)) {
  239. assert(0);
  240. return 0;
  241. }
  242. return 1;
  243. }
  244. int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
  245. return cbs_get_asn1(cbs, out, tag_value, 0 /* DER */,
  246. 1 /* skip header */);
  247. }
  248. int CBS_get_asn1_ber(CBS *cbs, CBS *out, unsigned tag_value) {
  249. return cbs_get_asn1(cbs, out, tag_value, 1 /* BER */,
  250. 1 /* skip header */);
  251. }
  252. int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
  253. return cbs_get_asn1(cbs, out, tag_value, 0 /* DER */,
  254. 0 /* include header */);
  255. }