/contrib/bsnmp/lib/asn1.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1022 lines · 760 code · 96 blank · 166 comment · 205 complexity · ecdbec4225147616aaa2fbc0324824f6 MD5 · raw file

  1. /*
  2. * Copyright (c) 2001-2003
  3. * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
  4. * All rights reserved.
  5. *
  6. * Author: Harti Brandt <harti@freebsd.org>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. *
  29. * $Begemot: bsnmp/lib/asn1.c,v 1.31 2005/10/06 07:14:58 brandt_h Exp $
  30. *
  31. * ASN.1 for SNMP.
  32. */
  33. #include <sys/types.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <stdarg.h>
  37. #include <string.h>
  38. #ifdef HAVE_STDINT_H
  39. #include <stdint.h>
  40. #elif defined(HAVE_INTTYPES_H)
  41. #include <inttypes.h>
  42. #endif
  43. #include <assert.h>
  44. #include "support.h"
  45. #include "asn1.h"
  46. static void asn_error_func(const struct asn_buf *, const char *, ...);
  47. void (*asn_error)(const struct asn_buf *, const char *, ...) = asn_error_func;
  48. /*
  49. * Read the next header. This reads the tag (note, that only single
  50. * byte tags are supported for now) and the length field. The length field
  51. * is restricted to a 32-bit value.
  52. * All errors of this function stop the decoding.
  53. */
  54. enum asn_err
  55. asn_get_header(struct asn_buf *b, u_char *type, asn_len_t *len)
  56. {
  57. u_int length;
  58. if (b->asn_len == 0) {
  59. asn_error(b, "no identifier for header");
  60. return (ASN_ERR_EOBUF);
  61. }
  62. *type = *b->asn_cptr;
  63. if ((*type & ASN_TYPE_MASK) > 0x30) {
  64. asn_error(b, "types > 0x30 not supported (%u)",
  65. *type & ASN_TYPE_MASK);
  66. return (ASN_ERR_FAILED);
  67. }
  68. b->asn_cptr++;
  69. b->asn_len--;
  70. if (b->asn_len == 0) {
  71. asn_error(b, "no length field");
  72. return (ASN_ERR_EOBUF);
  73. }
  74. if (*b->asn_cptr & 0x80) {
  75. length = *b->asn_cptr++ & 0x7f;
  76. b->asn_len--;
  77. if (length == 0) {
  78. asn_error(b, "indefinite length not supported");
  79. return (ASN_ERR_FAILED);
  80. }
  81. if (length > ASN_MAXLENLEN) {
  82. asn_error(b, "long length too long (%u)", length);
  83. return (ASN_ERR_FAILED);
  84. }
  85. if (length > b->asn_len) {
  86. asn_error(b, "long length truncated");
  87. return (ASN_ERR_EOBUF);
  88. }
  89. *len = 0;
  90. while (length--) {
  91. *len = (*len << 8) | *b->asn_cptr++;
  92. b->asn_len--;
  93. }
  94. } else {
  95. *len = *b->asn_cptr++;
  96. b->asn_len--;
  97. }
  98. return (ASN_ERR_OK);
  99. }
  100. /*
  101. * Write a length field (restricted to values < 2^32-1) and return the
  102. * number of bytes this field takes. If ptr is NULL, the length is computed
  103. * but nothing is written. If the length would be too large return 0.
  104. */
  105. static u_int
  106. asn_put_len(u_char *ptr, asn_len_t len)
  107. {
  108. u_int lenlen, lenlen1;
  109. asn_len_t tmp;
  110. if (len > ASN_MAXLEN) {
  111. asn_error(NULL, "encoding length too long: (%u)", len);
  112. return (0);
  113. }
  114. if (len <= 127) {
  115. if (ptr)
  116. *ptr++ = (u_char)len;
  117. return (1);
  118. } else {
  119. lenlen = 0;
  120. /* compute number of bytes for value (is at least 1) */
  121. for (tmp = len; tmp != 0; tmp >>= 8)
  122. lenlen++;
  123. if (ptr != NULL) {
  124. *ptr++ = (u_char)lenlen | 0x80;
  125. lenlen1 = lenlen;
  126. while (lenlen1-- > 0) {
  127. ptr[lenlen1] = len & 0xff;
  128. len >>= 8;
  129. }
  130. }
  131. return (lenlen + 1);
  132. }
  133. }
  134. /*
  135. * Write a header (tag and length fields).
  136. * Tags are restricted to one byte tags (value <= 0x30) and the
  137. * lenght field to 16-bit. All errors stop the encoding.
  138. */
  139. enum asn_err
  140. asn_put_header(struct asn_buf *b, u_char type, asn_len_t len)
  141. {
  142. u_int lenlen;
  143. /* tag field */
  144. if ((type & ASN_TYPE_MASK) > 0x30) {
  145. asn_error(NULL, "types > 0x30 not supported (%u)",
  146. type & ASN_TYPE_MASK);
  147. return (ASN_ERR_FAILED);
  148. }
  149. if (b->asn_len == 0)
  150. return (ASN_ERR_EOBUF);
  151. *b->asn_ptr++ = type;
  152. b->asn_len--;
  153. /* length field */
  154. if ((lenlen = asn_put_len(NULL, len)) == 0)
  155. return (ASN_ERR_FAILED);
  156. if (b->asn_len < lenlen)
  157. return (ASN_ERR_EOBUF);
  158. (void)asn_put_len(b->asn_ptr, len);
  159. b->asn_ptr += lenlen;
  160. b->asn_len -= lenlen;
  161. return (ASN_ERR_OK);
  162. }
  163. /*
  164. * This constructs a temporary sequence header with space for the maximum
  165. * length field (three byte). Set the pointer that ptr points to to the
  166. * start of the encoded header. This is used for a later call to
  167. * asn_commit_header which will fix-up the length field and move the
  168. * value if needed. All errors should stop the encoding.
  169. */
  170. #define TEMP_LEN (1 + ASN_MAXLENLEN + 1)
  171. enum asn_err
  172. asn_put_temp_header(struct asn_buf *b, u_char type, u_char **ptr)
  173. {
  174. int ret;
  175. if (b->asn_len < TEMP_LEN)
  176. return (ASN_ERR_EOBUF);
  177. *ptr = b->asn_ptr;
  178. if ((ret = asn_put_header(b, type, ASN_MAXLEN)) == ASN_ERR_OK)
  179. assert(b->asn_ptr == *ptr + TEMP_LEN);
  180. return (ret);
  181. }
  182. enum asn_err
  183. asn_commit_header(struct asn_buf *b, u_char *ptr, size_t *moved)
  184. {
  185. asn_len_t len;
  186. u_int lenlen, shift;
  187. /* compute length of encoded value without header */
  188. len = b->asn_ptr - (ptr + TEMP_LEN);
  189. /* insert length. may not fail. */
  190. lenlen = asn_put_len(ptr + 1, len);
  191. if (lenlen > TEMP_LEN - 1)
  192. return (ASN_ERR_FAILED);
  193. if (lenlen < TEMP_LEN - 1) {
  194. /* shift value down */
  195. shift = (TEMP_LEN - 1) - lenlen;
  196. memmove(ptr + 1 + lenlen, ptr + TEMP_LEN, len);
  197. b->asn_ptr -= shift;
  198. b->asn_len += shift;
  199. if (moved != NULL)
  200. *moved = shift;
  201. }
  202. return (ASN_ERR_OK);
  203. }
  204. #undef TEMP_LEN
  205. /*
  206. * BER integer. This may be used to get a signed 64 bit integer at maximum.
  207. * The maximum length should be checked by the caller. This cannot overflow
  208. * if the caller ensures that len is at maximum 8.
  209. *
  210. * <bytes>
  211. */
  212. static enum asn_err
  213. asn_get_real_integer(struct asn_buf *b, asn_len_t len, int64_t *vp)
  214. {
  215. uint64_t val;
  216. int neg = 0;
  217. enum asn_err err;
  218. if (b->asn_len < len) {
  219. asn_error(b, "truncated integer");
  220. return (ASN_ERR_EOBUF);
  221. }
  222. if (len == 0) {
  223. asn_error(b, "zero-length integer");
  224. *vp = 0;
  225. return (ASN_ERR_BADLEN);
  226. }
  227. err = ASN_ERR_OK;
  228. if (len > 8)
  229. err = ASN_ERR_RANGE;
  230. else if (len > 1 &&
  231. ((*b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) ||
  232. (*b->asn_cptr == 0xff && (b->asn_cptr[1] & 0x80) == 0x80))) {
  233. asn_error(b, "non-minimal integer");
  234. err = ASN_ERR_BADLEN;
  235. }
  236. if (*b->asn_cptr & 0x80)
  237. neg = 1;
  238. val = 0;
  239. while (len--) {
  240. val <<= 8;
  241. val |= neg ? (u_char)~*b->asn_cptr : *b->asn_cptr;
  242. b->asn_len--;
  243. b->asn_cptr++;
  244. }
  245. if (neg) {
  246. *vp = -(int64_t)val - 1;
  247. } else
  248. *vp = (int64_t)val;
  249. return (err);
  250. }
  251. /*
  252. * Write a signed integer with the given type. The caller has to ensure
  253. * that the actual value is ok for this type.
  254. */
  255. static enum asn_err
  256. asn_put_real_integer(struct asn_buf *b, u_char type, int64_t ival)
  257. {
  258. int i, neg = 0;
  259. # define OCTETS 8
  260. u_char buf[OCTETS];
  261. uint64_t val;
  262. enum asn_err ret;
  263. if (ival < 0) {
  264. /* this may fail if |INT64_MIN| > |INT64_MAX| and
  265. * the value is between * INT64_MIN <= ival < -(INT64_MAX+1) */
  266. val = (uint64_t)-(ival + 1);
  267. neg = 1;
  268. } else
  269. val = (uint64_t)ival;
  270. /* split the value into octets */
  271. for (i = OCTETS - 1; i >= 0; i--) {
  272. buf[i] = val & 0xff;
  273. if (neg)
  274. buf[i] = ~buf[i];
  275. val >>= 8;
  276. }
  277. /* no leading 9 zeroes or ones */
  278. for (i = 0; i < OCTETS - 1; i++)
  279. if (!((buf[i] == 0xff && (buf[i + 1] & 0x80) != 0) ||
  280. (buf[i] == 0x00 && (buf[i + 1] & 0x80) == 0)))
  281. break;
  282. if ((ret = asn_put_header(b, type, OCTETS - i)))
  283. return (ret);
  284. if (OCTETS - (u_int)i > b->asn_len)
  285. return (ASN_ERR_EOBUF);
  286. while (i < OCTETS) {
  287. *b->asn_ptr++ = buf[i++];
  288. b->asn_len--;
  289. }
  290. return (ASN_ERR_OK);
  291. # undef OCTETS
  292. }
  293. /*
  294. * The same for unsigned 64-bitters. Here we have the problem, that overflow
  295. * can happen, because the value maybe 9 bytes long. In this case the
  296. * first byte must be 0.
  297. */
  298. static enum asn_err
  299. asn_get_real_unsigned(struct asn_buf *b, asn_len_t len, uint64_t *vp)
  300. {
  301. enum asn_err err;
  302. if (b->asn_len < len) {
  303. asn_error(b, "truncated integer");
  304. return (ASN_ERR_EOBUF);
  305. }
  306. if (len == 0) {
  307. asn_error(b, "zero-length integer");
  308. *vp = 0;
  309. return (ASN_ERR_BADLEN);
  310. }
  311. err = ASN_ERR_OK;
  312. *vp = 0;
  313. if ((*b->asn_cptr & 0x80) || (len == 9 && *b->asn_cptr != 0)) {
  314. /* negative integer or too larger */
  315. *vp = 0xffffffffffffffffULL;
  316. err = ASN_ERR_RANGE;
  317. } else if (len > 1 &&
  318. *b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) {
  319. asn_error(b, "non-minimal unsigned");
  320. err = ASN_ERR_BADLEN;
  321. }
  322. while (len--) {
  323. *vp = (*vp << 8) | *b->asn_cptr++;
  324. b->asn_len--;
  325. }
  326. return (err);
  327. }
  328. /*
  329. * Values with the msb on need 9 octets.
  330. */
  331. static int
  332. asn_put_real_unsigned(struct asn_buf *b, u_char type, uint64_t val)
  333. {
  334. int i;
  335. # define OCTETS 9
  336. u_char buf[OCTETS];
  337. enum asn_err ret;
  338. /* split the value into octets */
  339. for (i = OCTETS - 1; i >= 0; i--) {
  340. buf[i] = val & 0xff;
  341. val >>= 8;
  342. }
  343. /* no leading 9 zeroes */
  344. for (i = 0; i < OCTETS - 1; i++)
  345. if (!(buf[i] == 0x00 && (buf[i + 1] & 0x80) == 0))
  346. break;
  347. if ((ret = asn_put_header(b, type, OCTETS - i)))
  348. return (ret);
  349. if (OCTETS - (u_int)i > b->asn_len)
  350. return (ASN_ERR_EOBUF);
  351. while (i < OCTETS) {
  352. *b->asn_ptr++ = buf[i++];
  353. b->asn_len--;
  354. }
  355. #undef OCTETS
  356. return (ASN_ERR_OK);
  357. }
  358. /*
  359. * The ASN.1 INTEGER type is restricted to 32-bit signed by the SMI.
  360. */
  361. enum asn_err
  362. asn_get_integer_raw(struct asn_buf *b, asn_len_t len, int32_t *vp)
  363. {
  364. int64_t val;
  365. enum asn_err ret;
  366. if ((ret = asn_get_real_integer(b, len, &val)) == ASN_ERR_OK) {
  367. if (len > 4)
  368. ret = ASN_ERR_BADLEN;
  369. else if (val > INT32_MAX || val < INT32_MIN)
  370. /* may not happen */
  371. ret = ASN_ERR_RANGE;
  372. *vp = (int32_t)val;
  373. }
  374. return (ret);
  375. }
  376. enum asn_err
  377. asn_get_integer(struct asn_buf *b, int32_t *vp)
  378. {
  379. asn_len_t len;
  380. u_char type;
  381. enum asn_err err;
  382. if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
  383. return (err);
  384. if (type != ASN_TYPE_INTEGER) {
  385. asn_error(b, "bad type for integer (%u)", type);
  386. return (ASN_ERR_TAG);
  387. }
  388. return (asn_get_integer_raw(b, len, vp));
  389. }
  390. enum asn_err
  391. asn_put_integer(struct asn_buf *b, int32_t val)
  392. {
  393. return (asn_put_real_integer(b, ASN_TYPE_INTEGER, val));
  394. }
  395. /*
  396. * OCTETSTRING
  397. *
  398. * <0x04> <len> <data ...>
  399. *
  400. * Get an octetstring. noctets must point to the buffer size and on
  401. * return will contain the size of the octetstring, regardless of the
  402. * buffer size.
  403. */
  404. enum asn_err
  405. asn_get_octetstring_raw(struct asn_buf *b, asn_len_t len, u_char *octets,
  406. u_int *noctets)
  407. {
  408. enum asn_err err = ASN_ERR_OK;
  409. if (*noctets < len) {
  410. asn_error(b, "octetstring truncated");
  411. err = ASN_ERR_RANGE;
  412. }
  413. if (b->asn_len < len) {
  414. asn_error(b, "truncatet octetstring");
  415. return (ASN_ERR_EOBUF);
  416. }
  417. if (*noctets < len)
  418. memcpy(octets, b->asn_cptr, *noctets);
  419. else
  420. memcpy(octets, b->asn_cptr, len);
  421. *noctets = len;
  422. b->asn_cptr += len;
  423. b->asn_len -= len;
  424. return (err);
  425. }
  426. enum asn_err
  427. asn_get_octetstring(struct asn_buf *b, u_char *octets, u_int *noctets)
  428. {
  429. enum asn_err err;
  430. u_char type;
  431. asn_len_t len;
  432. if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
  433. return (err);
  434. if (type != ASN_TYPE_OCTETSTRING) {
  435. asn_error(b, "bad type for octetstring (%u)", type);
  436. return (ASN_ERR_TAG);
  437. }
  438. return (asn_get_octetstring_raw(b, len, octets, noctets));
  439. }
  440. enum asn_err
  441. asn_put_octetstring(struct asn_buf *b, const u_char *octets, u_int noctets)
  442. {
  443. enum asn_err ret;
  444. if ((ret = asn_put_header(b, ASN_TYPE_OCTETSTRING, noctets)) != ASN_ERR_OK)
  445. return (ret);
  446. if (b->asn_len < noctets)
  447. return (ASN_ERR_EOBUF);
  448. memcpy(b->asn_ptr, octets, noctets);
  449. b->asn_ptr += noctets;
  450. b->asn_len -= noctets;
  451. return (ASN_ERR_OK);
  452. }
  453. /*
  454. * NULL
  455. *
  456. * <0x05> <0x00>
  457. */
  458. enum asn_err
  459. asn_get_null_raw(struct asn_buf *b, asn_len_t len)
  460. {
  461. if (len != 0) {
  462. if (b->asn_len < len) {
  463. asn_error(b, "truncated NULL");
  464. return (ASN_ERR_EOBUF);
  465. }
  466. asn_error(b, "bad length for NULL (%u)", len);
  467. b->asn_len -= len;
  468. b->asn_ptr += len;
  469. return (ASN_ERR_BADLEN);
  470. }
  471. return (ASN_ERR_OK);
  472. }
  473. enum asn_err
  474. asn_get_null(struct asn_buf *b)
  475. {
  476. u_char type;
  477. asn_len_t len;
  478. enum asn_err err;
  479. if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
  480. return (err);
  481. if (type != ASN_TYPE_NULL) {
  482. asn_error(b, "bad type for NULL (%u)", type);
  483. return (ASN_ERR_TAG);
  484. }
  485. return (asn_get_null_raw(b, len));
  486. }
  487. enum asn_err
  488. asn_put_null(struct asn_buf *b)
  489. {
  490. return (asn_put_header(b, ASN_TYPE_NULL, 0));
  491. }
  492. enum asn_err
  493. asn_put_exception(struct asn_buf *b, u_int except)
  494. {
  495. return (asn_put_header(b, ASN_CLASS_CONTEXT | except, 0));
  496. }
  497. /*
  498. * OBJID
  499. *
  500. * <0x06> <len> <subid...>
  501. */
  502. enum asn_err
  503. asn_get_objid_raw(struct asn_buf *b, asn_len_t len, struct asn_oid *oid)
  504. {
  505. asn_subid_t subid;
  506. enum asn_err err;
  507. if (b->asn_len < len) {
  508. asn_error(b, "truncated OBJID");
  509. return (ASN_ERR_EOBUF);
  510. }
  511. oid->len = 0;
  512. if (len == 0) {
  513. asn_error(b, "short OBJID");
  514. oid->subs[oid->len++] = 0;
  515. oid->subs[oid->len++] = 0;
  516. return (ASN_ERR_BADLEN);
  517. }
  518. err = ASN_ERR_OK;
  519. while (len != 0) {
  520. if (oid->len == ASN_MAXOIDLEN) {
  521. asn_error(b, "OID too long (%u)", oid->len);
  522. b->asn_cptr += len;
  523. b->asn_len -= len;
  524. return (ASN_ERR_BADLEN);
  525. }
  526. subid = 0;
  527. do {
  528. if (len == 0) {
  529. asn_error(b, "unterminated subid");
  530. return (ASN_ERR_EOBUF);
  531. }
  532. if (subid > (ASN_MAXID >> 7)) {
  533. asn_error(b, "OBID subid too larger");
  534. err = ASN_ERR_RANGE;
  535. }
  536. subid = (subid << 7) | (*b->asn_cptr & 0x7f);
  537. len--;
  538. b->asn_len--;
  539. } while (*b->asn_cptr++ & 0x80);
  540. if (oid->len == 0) {
  541. if (subid < 80) {
  542. oid->subs[oid->len++] = subid / 40;
  543. oid->subs[oid->len++] = subid % 40;
  544. } else {
  545. oid->subs[oid->len++] = 2;
  546. oid->subs[oid->len++] = subid - 80;
  547. }
  548. } else {
  549. oid->subs[oid->len++] = subid;
  550. }
  551. }
  552. return (err);
  553. }
  554. enum asn_err
  555. asn_get_objid(struct asn_buf *b, struct asn_oid *oid)
  556. {
  557. u_char type;
  558. asn_len_t len;
  559. enum asn_err err;
  560. if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
  561. return (err);
  562. if (type != ASN_TYPE_OBJID) {
  563. asn_error(b, "bad type for OBJID (%u)", type);
  564. return (ASN_ERR_TAG);
  565. }
  566. return (asn_get_objid_raw(b, len, oid));
  567. }
  568. enum asn_err
  569. asn_put_objid(struct asn_buf *b, const struct asn_oid *oid)
  570. {
  571. asn_subid_t first, sub;
  572. enum asn_err err, err1;
  573. u_int i, oidlen;
  574. asn_len_t len;
  575. err = ASN_ERR_OK;
  576. if (oid->len == 0) {
  577. /* illegal */
  578. asn_error(NULL, "short oid");
  579. err = ASN_ERR_RANGE;
  580. first = 0;
  581. oidlen = 2;
  582. } else if (oid->len == 1) {
  583. /* illegal */
  584. asn_error(b, "short oid");
  585. if (oid->subs[0] > 2)
  586. asn_error(NULL, "oid[0] too large (%u)", oid->subs[0]);
  587. err = ASN_ERR_RANGE;
  588. first = oid->subs[0] * 40;
  589. oidlen = 2;
  590. } else {
  591. if (oid->len > ASN_MAXOIDLEN) {
  592. asn_error(NULL, "oid too long %u", oid->len);
  593. err = ASN_ERR_RANGE;
  594. }
  595. if (oid->subs[0] > 2 ||
  596. (oid->subs[0] < 2 && oid->subs[0] >= 40)) {
  597. asn_error(NULL, "oid out of range (%u,%u)",
  598. oid->subs[0], oid->subs[1]);
  599. err = ASN_ERR_RANGE;
  600. }
  601. first = 40 * oid->subs[0] + oid->subs[1];
  602. oidlen = oid->len;
  603. }
  604. len = 0;
  605. for (i = 1; i < oidlen; i++) {
  606. sub = (i == 1) ? first : oid->subs[i];
  607. if (sub > ASN_MAXID) {
  608. asn_error(NULL, "oid subid too large");
  609. err = ASN_ERR_RANGE;
  610. }
  611. len += (sub <= 0x7f) ? 1
  612. : (sub <= 0x3fff) ? 2
  613. : (sub <= 0x1fffff) ? 3
  614. : (sub <= 0xfffffff) ? 4
  615. : 5;
  616. }
  617. if ((err1 = asn_put_header(b, ASN_TYPE_OBJID, len)) != ASN_ERR_OK)
  618. return (err1);
  619. if (b->asn_len < len)
  620. return (ASN_ERR_EOBUF);
  621. for (i = 1; i < oidlen; i++) {
  622. sub = (i == 1) ? first : oid->subs[i];
  623. if (sub <= 0x7f) {
  624. *b->asn_ptr++ = sub;
  625. b->asn_len--;
  626. } else if (sub <= 0x3fff) {
  627. *b->asn_ptr++ = (sub >> 7) | 0x80;
  628. *b->asn_ptr++ = sub & 0x7f;
  629. b->asn_len -= 2;
  630. } else if (sub <= 0x1fffff) {
  631. *b->asn_ptr++ = (sub >> 14) | 0x80;
  632. *b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80;
  633. *b->asn_ptr++ = sub & 0x7f;
  634. b->asn_len -= 3;
  635. } else if (sub <= 0xfffffff) {
  636. *b->asn_ptr++ = (sub >> 21) | 0x80;
  637. *b->asn_ptr++ = ((sub >> 14) & 0x7f) | 0x80;
  638. *b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80;
  639. *b->asn_ptr++ = sub & 0x7f;
  640. b->asn_len -= 4;
  641. } else {
  642. *b->asn_ptr++ = (sub >> 28) | 0x80;
  643. *b->asn_ptr++ = ((sub >> 21) & 0x7f) | 0x80;
  644. *b->asn_ptr++ = ((sub >> 14) & 0x7f) | 0x80;
  645. *b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80;
  646. *b->asn_ptr++ = sub & 0x7f;
  647. b->asn_len -= 5;
  648. }
  649. }
  650. return (err);
  651. }
  652. /*
  653. * SEQUENCE header
  654. *
  655. * <0x10|0x20> <len> <data...>
  656. */
  657. enum asn_err
  658. asn_get_sequence(struct asn_buf *b, asn_len_t *len)
  659. {
  660. u_char type;
  661. enum asn_err err;
  662. if ((err = asn_get_header(b, &type, len)) != ASN_ERR_OK)
  663. return (err);
  664. if (type != (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED)) {
  665. asn_error(b, "bad sequence type %u", type);
  666. return (ASN_ERR_TAG);
  667. }
  668. if (*len > b->asn_len) {
  669. asn_error(b, "truncated sequence");
  670. return (ASN_ERR_EOBUF);
  671. }
  672. return (ASN_ERR_OK);
  673. }
  674. /*
  675. * Application types
  676. *
  677. * 0x40 4 MSB 2MSB 2LSB LSB
  678. */
  679. enum asn_err
  680. asn_get_ipaddress_raw(struct asn_buf *b, asn_len_t len, u_char *addr)
  681. {
  682. u_int i;
  683. if (b->asn_len < len) {
  684. asn_error(b, "truncated ip-address");
  685. return (ASN_ERR_EOBUF);
  686. }
  687. if (len < 4) {
  688. asn_error(b, "short length for ip-Address %u", len);
  689. for (i = 0; i < len; i++)
  690. *addr++ = *b->asn_cptr++;
  691. while (i++ < len)
  692. *addr++ = 0;
  693. b->asn_len -= len;
  694. return (ASN_ERR_BADLEN);
  695. }
  696. for (i = 0; i < 4; i++)
  697. *addr++ = *b->asn_cptr++;
  698. b->asn_cptr += len - 4;
  699. b->asn_len -= len;
  700. return (ASN_ERR_OK);
  701. }
  702. enum asn_err
  703. asn_get_ipaddress(struct asn_buf *b, u_char *addr)
  704. {
  705. u_char type;
  706. asn_len_t len;
  707. enum asn_err err;
  708. if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
  709. return (err);
  710. if (type != (ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS)) {
  711. asn_error(b, "bad type for ip-address %u", type);
  712. return (ASN_ERR_TAG);
  713. }
  714. return (asn_get_ipaddress_raw(b, len, addr));
  715. }
  716. enum asn_err
  717. asn_put_ipaddress(struct asn_buf *b, const u_char *addr)
  718. {
  719. enum asn_err err;
  720. if ((err = asn_put_header(b, ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS,
  721. 4)) != ASN_ERR_OK)
  722. return (err);
  723. if (b->asn_len < 4)
  724. return (ASN_ERR_EOBUF);
  725. memcpy(b->asn_ptr, addr, 4);
  726. b->asn_ptr += 4;
  727. b->asn_len -= 4;
  728. return (ASN_ERR_OK);
  729. }
  730. /*
  731. * UNSIGNED32
  732. *
  733. * 0x42|0x41 <len> ...
  734. */
  735. enum asn_err
  736. asn_get_uint32_raw(struct asn_buf *b, asn_len_t len, uint32_t *vp)
  737. {
  738. uint64_t v;
  739. enum asn_err err;
  740. if ((err = asn_get_real_unsigned(b, len, &v)) == ASN_ERR_OK) {
  741. if (len > 5) {
  742. asn_error(b, "uint32 too long %u", len);
  743. err = ASN_ERR_BADLEN;
  744. } else if (v > UINT32_MAX) {
  745. asn_error(b, "uint32 too large %llu", v);
  746. err = ASN_ERR_RANGE;
  747. }
  748. *vp = (uint32_t)v;
  749. }
  750. return (err);
  751. }
  752. enum asn_err
  753. asn_put_uint32(struct asn_buf *b, u_char type, uint32_t val)
  754. {
  755. uint64_t v = val;
  756. return (asn_put_real_unsigned(b, ASN_CLASS_APPLICATION|type, v));
  757. }
  758. /*
  759. * COUNTER64
  760. * 0x46 <len> ...
  761. */
  762. enum asn_err
  763. asn_get_counter64_raw(struct asn_buf *b, asn_len_t len, uint64_t *vp)
  764. {
  765. return (asn_get_real_unsigned(b, len, vp));
  766. }
  767. enum asn_err
  768. asn_put_counter64(struct asn_buf *b, uint64_t val)
  769. {
  770. return (asn_put_real_unsigned(b,
  771. ASN_CLASS_APPLICATION | ASN_APP_COUNTER64, val));
  772. }
  773. /*
  774. * TimeTicks
  775. * 0x43 <len> ...
  776. */
  777. enum asn_err
  778. asn_get_timeticks(struct asn_buf *b, uint32_t *vp)
  779. {
  780. asn_len_t len;
  781. u_char type;
  782. enum asn_err err;
  783. if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
  784. return (err);
  785. if (type != (ASN_CLASS_APPLICATION|ASN_APP_TIMETICKS)) {
  786. asn_error(b, "bad type for timeticks %u", type);
  787. return (ASN_ERR_TAG);
  788. }
  789. return (asn_get_uint32_raw(b, len, vp));
  790. }
  791. enum asn_err
  792. asn_put_timeticks(struct asn_buf *b, uint32_t val)
  793. {
  794. uint64_t v = val;
  795. return (asn_put_real_unsigned(b,
  796. ASN_CLASS_APPLICATION | ASN_APP_TIMETICKS, v));
  797. }
  798. /*
  799. * Construct a new OID by taking a range of sub ids of the original oid.
  800. */
  801. void
  802. asn_slice_oid(struct asn_oid *dest, const struct asn_oid *src,
  803. u_int from, u_int to)
  804. {
  805. if (from >= to) {
  806. dest->len = 0;
  807. return;
  808. }
  809. dest->len = to - from;
  810. memcpy(dest->subs, &src->subs[from], dest->len * sizeof(dest->subs[0]));
  811. }
  812. /*
  813. * Append from to to
  814. */
  815. void
  816. asn_append_oid(struct asn_oid *to, const struct asn_oid *from)
  817. {
  818. memcpy(&to->subs[to->len], &from->subs[0],
  819. from->len * sizeof(from->subs[0]));
  820. to->len += from->len;
  821. }
  822. /*
  823. * Skip a value
  824. */
  825. enum asn_err
  826. asn_skip(struct asn_buf *b, asn_len_t len)
  827. {
  828. if (b->asn_len < len)
  829. return (ASN_ERR_EOBUF);
  830. b->asn_cptr += len;
  831. b->asn_len -= len;
  832. return (ASN_ERR_OK);
  833. }
  834. /*
  835. * Add a padding
  836. */
  837. enum asn_err
  838. asn_pad(struct asn_buf *b, asn_len_t len)
  839. {
  840. if (b->asn_len < len)
  841. return (ASN_ERR_EOBUF);
  842. b->asn_ptr += len;
  843. b->asn_len -= len;
  844. return (ASN_ERR_OK);
  845. }
  846. /*
  847. * Compare two OIDs.
  848. *
  849. * o1 < o2 : -1
  850. * o1 > o2 : +1
  851. * o1 = o2 : 0
  852. */
  853. int
  854. asn_compare_oid(const struct asn_oid *o1, const struct asn_oid *o2)
  855. {
  856. u_long i;
  857. for (i = 0; i < o1->len && i < o2->len; i++) {
  858. if (o1->subs[i] < o2->subs[i])
  859. return (-1);
  860. if (o1->subs[i] > o2->subs[i])
  861. return (+1);
  862. }
  863. if (o1->len < o2->len)
  864. return (-1);
  865. if (o1->len > o2->len)
  866. return (+1);
  867. return (0);
  868. }
  869. /*
  870. * Check whether an OID is a sub-string of another OID.
  871. */
  872. int
  873. asn_is_suboid(const struct asn_oid *o1, const struct asn_oid *o2)
  874. {
  875. u_long i;
  876. for (i = 0; i < o1->len; i++)
  877. if (i >= o2->len || o1->subs[i] != o2->subs[i])
  878. return (0);
  879. return (1);
  880. }
  881. /*
  882. * Put a string representation of an oid into a user buffer. This buffer
  883. * is assumed to be at least ASN_OIDSTRLEN characters long.
  884. *
  885. * sprintf is assumed not to fail here.
  886. */
  887. char *
  888. asn_oid2str_r(const struct asn_oid *oid, char *buf)
  889. {
  890. u_int len, i;
  891. char *ptr;
  892. if ((len = oid->len) > ASN_MAXOIDLEN)
  893. len = ASN_MAXOIDLEN;
  894. buf[0] = '\0';
  895. for (i = 0, ptr = buf; i < len; i++) {
  896. if (i > 0)
  897. *ptr++ = '.';
  898. ptr += sprintf(ptr, "%u", oid->subs[i]);
  899. }
  900. return (buf);
  901. }
  902. /*
  903. * Make a string from an OID in a private buffer.
  904. */
  905. char *
  906. asn_oid2str(const struct asn_oid *oid)
  907. {
  908. static char str[ASN_OIDSTRLEN];
  909. return (asn_oid2str_r(oid, str));
  910. }
  911. static void
  912. asn_error_func(const struct asn_buf *b, const char *err, ...)
  913. {
  914. va_list ap;
  915. u_long i;
  916. fprintf(stderr, "ASN.1: ");
  917. va_start(ap, err);
  918. vfprintf(stderr, err, ap);
  919. va_end(ap);
  920. if (b != NULL) {
  921. fprintf(stderr, " at");
  922. for (i = 0; b->asn_len > i; i++)
  923. fprintf(stderr, " %02x", b->asn_cptr[i]);
  924. }
  925. fprintf(stderr, "\n");
  926. }