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.
 
 
 
 
 
 

416 lines
9.0 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. #include "internal.h"
  20. void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
  21. cbs->data = data;
  22. cbs->len = len;
  23. }
  24. static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
  25. if (cbs->len < n) {
  26. return 0;
  27. }
  28. *p = cbs->data;
  29. cbs->data += n;
  30. cbs->len -= n;
  31. return 1;
  32. }
  33. int CBS_skip(CBS *cbs, size_t len) {
  34. const uint8_t *dummy;
  35. return cbs_get(cbs, &dummy, len);
  36. }
  37. const uint8_t *CBS_data(const CBS *cbs) {
  38. return cbs->data;
  39. }
  40. size_t CBS_len(const CBS *cbs) {
  41. return cbs->len;
  42. }
  43. int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
  44. OPENSSL_free(*out_ptr);
  45. *out_ptr = NULL;
  46. *out_len = 0;
  47. if (cbs->len == 0) {
  48. return 1;
  49. }
  50. *out_ptr = BUF_memdup(cbs->data, cbs->len);
  51. if (*out_ptr == NULL) {
  52. return 0;
  53. }
  54. *out_len = cbs->len;
  55. return 1;
  56. }
  57. int CBS_strdup(const CBS *cbs, char **out_ptr) {
  58. if (*out_ptr != NULL) {
  59. OPENSSL_free(*out_ptr);
  60. }
  61. *out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
  62. return (*out_ptr != NULL);
  63. }
  64. int CBS_contains_zero_byte(const CBS *cbs) {
  65. return memchr(cbs->data, 0, cbs->len) != NULL;
  66. }
  67. int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
  68. if (len != cbs->len) {
  69. return 0;
  70. }
  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. int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) {
  118. const uint8_t *v;
  119. if (!cbs_get(cbs, &v, len)) {
  120. return 0;
  121. }
  122. memcpy(out, v, len);
  123. return 1;
  124. }
  125. static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
  126. uint32_t len;
  127. if (!cbs_get_u(cbs, &len, len_len)) {
  128. return 0;
  129. }
  130. return CBS_get_bytes(cbs, out, len);
  131. }
  132. int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
  133. return cbs_get_length_prefixed(cbs, out, 1);
  134. }
  135. int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
  136. return cbs_get_length_prefixed(cbs, out, 2);
  137. }
  138. int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
  139. return cbs_get_length_prefixed(cbs, out, 3);
  140. }
  141. static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
  142. size_t *out_header_len, int ber_ok) {
  143. uint8_t tag, length_byte;
  144. CBS header = *cbs;
  145. CBS throwaway;
  146. if (out == NULL) {
  147. out = &throwaway;
  148. }
  149. if (!CBS_get_u8(&header, &tag) ||
  150. !CBS_get_u8(&header, &length_byte)) {
  151. return 0;
  152. }
  153. if ((tag & 0x1f) == 0x1f) {
  154. /* Long form tags are not supported. */
  155. return 0;
  156. }
  157. if (out_tag != NULL) {
  158. *out_tag = tag;
  159. }
  160. size_t len;
  161. if ((length_byte & 0x80) == 0) {
  162. /* Short form length. */
  163. len = ((size_t) length_byte) + 2;
  164. if (out_header_len != NULL) {
  165. *out_header_len = 2;
  166. }
  167. } else {
  168. /* Long form length. */
  169. const size_t num_bytes = length_byte & 0x7f;
  170. uint32_t len32;
  171. if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
  172. /* indefinite length */
  173. if (out_header_len != NULL) {
  174. *out_header_len = 2;
  175. }
  176. return CBS_get_bytes(cbs, out, 2);
  177. }
  178. if (num_bytes == 0 || num_bytes > 4) {
  179. return 0;
  180. }
  181. if (!cbs_get_u(&header, &len32, num_bytes)) {
  182. return 0;
  183. }
  184. if (len32 < 128) {
  185. /* Length should have used short-form encoding. */
  186. return 0;
  187. }
  188. if ((len32 >> ((num_bytes-1)*8)) == 0) {
  189. /* Length should have been at least one byte shorter. */
  190. return 0;
  191. }
  192. len = len32;
  193. if (len + 2 + num_bytes < len) {
  194. /* Overflow. */
  195. return 0;
  196. }
  197. len += 2 + num_bytes;
  198. if (out_header_len != NULL) {
  199. *out_header_len = 2 + num_bytes;
  200. }
  201. }
  202. return CBS_get_bytes(cbs, out, len);
  203. }
  204. int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
  205. size_t *out_header_len) {
  206. return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
  207. 0 /* DER only */);
  208. }
  209. int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
  210. size_t *out_header_len) {
  211. return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
  212. 1 /* BER allowed */);
  213. }
  214. static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value,
  215. int skip_header) {
  216. size_t header_len;
  217. unsigned tag;
  218. CBS throwaway;
  219. if (out == NULL) {
  220. out = &throwaway;
  221. }
  222. if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
  223. tag != tag_value) {
  224. return 0;
  225. }
  226. if (skip_header && !CBS_skip(out, header_len)) {
  227. assert(0);
  228. return 0;
  229. }
  230. return 1;
  231. }
  232. int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
  233. return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
  234. }
  235. int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
  236. return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
  237. }
  238. int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
  239. if (CBS_len(cbs) < 1) {
  240. return 0;
  241. }
  242. return CBS_data(cbs)[0] == tag_value;
  243. }
  244. int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
  245. CBS bytes;
  246. const uint8_t *data;
  247. size_t i, len;
  248. if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
  249. return 0;
  250. }
  251. *out = 0;
  252. data = CBS_data(&bytes);
  253. len = CBS_len(&bytes);
  254. if (len == 0) {
  255. /* An INTEGER is encoded with at least one octet. */
  256. return 0;
  257. }
  258. if ((data[0] & 0x80) != 0) {
  259. /* Negative number. */
  260. return 0;
  261. }
  262. if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) {
  263. /* Extra leading zeros. */
  264. return 0;
  265. }
  266. for (i = 0; i < len; i++) {
  267. if ((*out >> 56) != 0) {
  268. /* Too large to represent as a uint64_t. */
  269. return 0;
  270. }
  271. *out <<= 8;
  272. *out |= data[i];
  273. }
  274. return 1;
  275. }
  276. int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
  277. int present = 0;
  278. if (CBS_peek_asn1_tag(cbs, tag)) {
  279. if (!CBS_get_asn1(cbs, out, tag)) {
  280. return 0;
  281. }
  282. present = 1;
  283. }
  284. if (out_present != NULL) {
  285. *out_present = present;
  286. }
  287. return 1;
  288. }
  289. int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
  290. unsigned tag) {
  291. CBS child;
  292. int present;
  293. if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
  294. return 0;
  295. }
  296. if (present) {
  297. if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
  298. CBS_len(&child) != 0) {
  299. return 0;
  300. }
  301. } else {
  302. CBS_init(out, NULL, 0);
  303. }
  304. if (out_present) {
  305. *out_present = present;
  306. }
  307. return 1;
  308. }
  309. int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag,
  310. uint64_t default_value) {
  311. CBS child;
  312. int present;
  313. if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
  314. return 0;
  315. }
  316. if (present) {
  317. if (!CBS_get_asn1_uint64(&child, out) ||
  318. CBS_len(&child) != 0) {
  319. return 0;
  320. }
  321. } else {
  322. *out = default_value;
  323. }
  324. return 1;
  325. }
  326. int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
  327. int default_value) {
  328. CBS child, child2;
  329. int present;
  330. if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
  331. return 0;
  332. }
  333. if (present) {
  334. uint8_t boolean;
  335. if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
  336. CBS_len(&child2) != 1 ||
  337. CBS_len(&child) != 0) {
  338. return 0;
  339. }
  340. boolean = CBS_data(&child2)[0];
  341. if (boolean == 0) {
  342. *out = 0;
  343. } else if (boolean == 0xff) {
  344. *out = 1;
  345. } else {
  346. return 0;
  347. }
  348. } else {
  349. *out = default_value;
  350. }
  351. return 1;
  352. }