tasn_enc.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. /* tasn_enc.c */
  2. /*
  3. * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
  4. * 2000.
  5. */
  6. /* ====================================================================
  7. * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. *
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in
  18. * the documentation and/or other materials provided with the
  19. * distribution.
  20. *
  21. * 3. All advertising materials mentioning features or use of this
  22. * software must display the following acknowledgment:
  23. * "This product includes software developed by the OpenSSL Project
  24. * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  25. *
  26. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  27. * endorse or promote products derived from this software without
  28. * prior written permission. For written permission, please contact
  29. * licensing@OpenSSL.org.
  30. *
  31. * 5. Products derived from this software may not be called "OpenSSL"
  32. * nor may "OpenSSL" appear in their names without prior written
  33. * permission of the OpenSSL Project.
  34. *
  35. * 6. Redistributions of any form whatsoever must retain the following
  36. * acknowledgment:
  37. * "This product includes software developed by the OpenSSL Project
  38. * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  41. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  43. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  44. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  45. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  46. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  47. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  49. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  50. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  51. * OF THE POSSIBILITY OF SUCH DAMAGE.
  52. * ====================================================================
  53. *
  54. * This product includes cryptographic software written by Eric Young
  55. * (eay@cryptsoft.com). This product includes software written by Tim
  56. * Hudson (tjh@cryptsoft.com).
  57. *
  58. */
  59. #include <stddef.h>
  60. #include <string.h>
  61. #include <limits.h>
  62. #include "cryptlib.h"
  63. #include <openssl/asn1.h>
  64. #include <openssl/asn1t.h>
  65. #include <openssl/objects.h>
  66. static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
  67. const ASN1_ITEM *it, int tag, int aclass);
  68. static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
  69. int skcontlen, const ASN1_ITEM *item,
  70. int do_sort, int iclass);
  71. static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
  72. const ASN1_TEMPLATE *tt, int tag, int aclass);
  73. static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
  74. const ASN1_ITEM *it, int flags);
  75. /*
  76. * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
  77. * indefinite length constructed encoding, where appropriate
  78. */
  79. int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
  80. const ASN1_ITEM *it)
  81. {
  82. return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
  83. }
  84. int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
  85. {
  86. return asn1_item_flags_i2d(val, out, it, 0);
  87. }
  88. /*
  89. * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
  90. * points to a buffer to output the data to. The new i2d has one additional
  91. * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
  92. * allocated and populated with the encoding.
  93. */
  94. static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
  95. const ASN1_ITEM *it, int flags)
  96. {
  97. if (out && !*out) {
  98. unsigned char *p, *buf;
  99. int len;
  100. len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
  101. if (len <= 0)
  102. return len;
  103. buf = OPENSSL_malloc(len);
  104. if (!buf)
  105. return -1;
  106. p = buf;
  107. ASN1_item_ex_i2d(&val, &p, it, -1, flags);
  108. *out = buf;
  109. return len;
  110. }
  111. return ASN1_item_ex_i2d(&val, out, it, -1, flags);
  112. }
  113. /*
  114. * Encode an item, taking care of IMPLICIT tagging (if any). This function
  115. * performs the normal item handling: it can be used in external types.
  116. */
  117. int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
  118. const ASN1_ITEM *it, int tag, int aclass)
  119. {
  120. const ASN1_TEMPLATE *tt = NULL;
  121. unsigned char *p = NULL;
  122. int i, seqcontlen, seqlen, ndef = 1;
  123. const ASN1_COMPAT_FUNCS *cf;
  124. const ASN1_EXTERN_FUNCS *ef;
  125. const ASN1_AUX *aux = it->funcs;
  126. ASN1_aux_cb *asn1_cb = 0;
  127. if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
  128. return 0;
  129. if (aux && aux->asn1_cb)
  130. asn1_cb = aux->asn1_cb;
  131. switch (it->itype) {
  132. case ASN1_ITYPE_PRIMITIVE:
  133. if (it->templates)
  134. return asn1_template_ex_i2d(pval, out, it->templates,
  135. tag, aclass);
  136. return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
  137. break;
  138. case ASN1_ITYPE_MSTRING:
  139. return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
  140. case ASN1_ITYPE_CHOICE:
  141. if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
  142. return 0;
  143. i = asn1_get_choice_selector(pval, it);
  144. if ((i >= 0) && (i < it->tcount)) {
  145. ASN1_VALUE **pchval;
  146. const ASN1_TEMPLATE *chtt;
  147. chtt = it->templates + i;
  148. pchval = asn1_get_field_ptr(pval, chtt);
  149. return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
  150. }
  151. /* Fixme: error condition if selector out of range */
  152. if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
  153. return 0;
  154. break;
  155. case ASN1_ITYPE_EXTERN:
  156. /* If new style i2d it does all the work */
  157. ef = it->funcs;
  158. return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
  159. case ASN1_ITYPE_COMPAT:
  160. /* old style hackery... */
  161. cf = it->funcs;
  162. if (out)
  163. p = *out;
  164. i = cf->asn1_i2d(*pval, out);
  165. /*
  166. * Fixup for IMPLICIT tag: note this messes up for tags > 30, but so
  167. * did the old code. Tags > 30 are very rare anyway.
  168. */
  169. if (out && (tag != -1))
  170. *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
  171. return i;
  172. case ASN1_ITYPE_NDEF_SEQUENCE:
  173. /* Use indefinite length constructed if requested */
  174. if (aclass & ASN1_TFLG_NDEF)
  175. ndef = 2;
  176. /* fall through */
  177. case ASN1_ITYPE_SEQUENCE:
  178. i = asn1_enc_restore(&seqcontlen, out, pval, it);
  179. /* An error occurred */
  180. if (i < 0)
  181. return 0;
  182. /* We have a valid cached encoding... */
  183. if (i > 0)
  184. return seqcontlen;
  185. /* Otherwise carry on */
  186. seqcontlen = 0;
  187. /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
  188. if (tag == -1) {
  189. tag = V_ASN1_SEQUENCE;
  190. /* Retain any other flags in aclass */
  191. aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
  192. | V_ASN1_UNIVERSAL;
  193. }
  194. if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
  195. return 0;
  196. /* First work out sequence content length */
  197. for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
  198. const ASN1_TEMPLATE *seqtt;
  199. ASN1_VALUE **pseqval;
  200. int tmplen;
  201. seqtt = asn1_do_adb(pval, tt, 1);
  202. if (!seqtt)
  203. return 0;
  204. pseqval = asn1_get_field_ptr(pval, seqtt);
  205. tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
  206. if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
  207. return -1;
  208. seqcontlen += tmplen;
  209. }
  210. seqlen = ASN1_object_size(ndef, seqcontlen, tag);
  211. if (!out || seqlen == -1)
  212. return seqlen;
  213. /* Output SEQUENCE header */
  214. ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
  215. for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
  216. const ASN1_TEMPLATE *seqtt;
  217. ASN1_VALUE **pseqval;
  218. seqtt = asn1_do_adb(pval, tt, 1);
  219. if (!seqtt)
  220. return 0;
  221. pseqval = asn1_get_field_ptr(pval, seqtt);
  222. /* FIXME: check for errors in enhanced version */
  223. asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
  224. }
  225. if (ndef == 2)
  226. ASN1_put_eoc(out);
  227. if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
  228. return 0;
  229. return seqlen;
  230. default:
  231. return 0;
  232. }
  233. return 0;
  234. }
  235. int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
  236. const ASN1_TEMPLATE *tt)
  237. {
  238. return asn1_template_ex_i2d(pval, out, tt, -1, 0);
  239. }
  240. static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
  241. const ASN1_TEMPLATE *tt, int tag, int iclass)
  242. {
  243. int i, ret, flags, ttag, tclass, ndef;
  244. flags = tt->flags;
  245. /*
  246. * Work out tag and class to use: tagging may come either from the
  247. * template or the arguments, not both because this would create
  248. * ambiguity. Additionally the iclass argument may contain some
  249. * additional flags which should be noted and passed down to other
  250. * levels.
  251. */
  252. if (flags & ASN1_TFLG_TAG_MASK) {
  253. /* Error if argument and template tagging */
  254. if (tag != -1)
  255. /* FIXME: error code here */
  256. return -1;
  257. /* Get tagging from template */
  258. ttag = tt->tag;
  259. tclass = flags & ASN1_TFLG_TAG_CLASS;
  260. } else if (tag != -1) {
  261. /* No template tagging, get from arguments */
  262. ttag = tag;
  263. tclass = iclass & ASN1_TFLG_TAG_CLASS;
  264. } else {
  265. ttag = -1;
  266. tclass = 0;
  267. }
  268. /*
  269. * Remove any class mask from iflag.
  270. */
  271. iclass &= ~ASN1_TFLG_TAG_CLASS;
  272. /*
  273. * At this point 'ttag' contains the outer tag to use, 'tclass' is the
  274. * class and iclass is any flags passed to this function.
  275. */
  276. /* if template and arguments require ndef, use it */
  277. if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
  278. ndef = 2;
  279. else
  280. ndef = 1;
  281. if (flags & ASN1_TFLG_SK_MASK) {
  282. /* SET OF, SEQUENCE OF */
  283. STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
  284. int isset, sktag, skaclass;
  285. int skcontlen, sklen;
  286. ASN1_VALUE *skitem;
  287. if (!*pval)
  288. return 0;
  289. if (flags & ASN1_TFLG_SET_OF) {
  290. isset = 1;
  291. /* 2 means we reorder */
  292. if (flags & ASN1_TFLG_SEQUENCE_OF)
  293. isset = 2;
  294. } else
  295. isset = 0;
  296. /*
  297. * Work out inner tag value: if EXPLICIT or no tagging use underlying
  298. * type.
  299. */
  300. if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
  301. sktag = ttag;
  302. skaclass = tclass;
  303. } else {
  304. skaclass = V_ASN1_UNIVERSAL;
  305. if (isset)
  306. sktag = V_ASN1_SET;
  307. else
  308. sktag = V_ASN1_SEQUENCE;
  309. }
  310. /* Determine total length of items */
  311. skcontlen = 0;
  312. for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
  313. int tmplen;
  314. skitem = sk_ASN1_VALUE_value(sk, i);
  315. tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
  316. -1, iclass);
  317. if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
  318. return -1;
  319. skcontlen += tmplen;
  320. }
  321. sklen = ASN1_object_size(ndef, skcontlen, sktag);
  322. if (sklen == -1)
  323. return -1;
  324. /* If EXPLICIT need length of surrounding tag */
  325. if (flags & ASN1_TFLG_EXPTAG)
  326. ret = ASN1_object_size(ndef, sklen, ttag);
  327. else
  328. ret = sklen;
  329. if (!out || ret == -1)
  330. return ret;
  331. /* Now encode this lot... */
  332. /* EXPLICIT tag */
  333. if (flags & ASN1_TFLG_EXPTAG)
  334. ASN1_put_object(out, ndef, sklen, ttag, tclass);
  335. /* SET or SEQUENCE and IMPLICIT tag */
  336. ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
  337. /* And the stuff itself */
  338. asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
  339. isset, iclass);
  340. if (ndef == 2) {
  341. ASN1_put_eoc(out);
  342. if (flags & ASN1_TFLG_EXPTAG)
  343. ASN1_put_eoc(out);
  344. }
  345. return ret;
  346. }
  347. if (flags & ASN1_TFLG_EXPTAG) {
  348. /* EXPLICIT tagging */
  349. /* Find length of tagged item */
  350. i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
  351. if (!i)
  352. return 0;
  353. /* Find length of EXPLICIT tag */
  354. ret = ASN1_object_size(ndef, i, ttag);
  355. if (out && ret != -1) {
  356. /* Output tag and item */
  357. ASN1_put_object(out, ndef, i, ttag, tclass);
  358. ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
  359. if (ndef == 2)
  360. ASN1_put_eoc(out);
  361. }
  362. return ret;
  363. }
  364. /* Either normal or IMPLICIT tagging: combine class and flags */
  365. return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
  366. ttag, tclass | iclass);
  367. }
  368. /* Temporary structure used to hold DER encoding of items for SET OF */
  369. typedef struct {
  370. unsigned char *data;
  371. int length;
  372. ASN1_VALUE *field;
  373. } DER_ENC;
  374. static int der_cmp(const void *a, const void *b)
  375. {
  376. const DER_ENC *d1 = a, *d2 = b;
  377. int cmplen, i;
  378. cmplen = (d1->length < d2->length) ? d1->length : d2->length;
  379. i = memcmp(d1->data, d2->data, cmplen);
  380. if (i)
  381. return i;
  382. return d1->length - d2->length;
  383. }
  384. /* Output the content octets of SET OF or SEQUENCE OF */
  385. static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
  386. int skcontlen, const ASN1_ITEM *item,
  387. int do_sort, int iclass)
  388. {
  389. int i;
  390. ASN1_VALUE *skitem;
  391. unsigned char *tmpdat = NULL, *p = NULL;
  392. DER_ENC *derlst = NULL, *tder;
  393. if (do_sort) {
  394. /* Don't need to sort less than 2 items */
  395. if (sk_ASN1_VALUE_num(sk) < 2)
  396. do_sort = 0;
  397. else {
  398. derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
  399. * sizeof(*derlst));
  400. if (!derlst)
  401. return 0;
  402. tmpdat = OPENSSL_malloc(skcontlen);
  403. if (!tmpdat) {
  404. OPENSSL_free(derlst);
  405. return 0;
  406. }
  407. }
  408. }
  409. /* If not sorting just output each item */
  410. if (!do_sort) {
  411. for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
  412. skitem = sk_ASN1_VALUE_value(sk, i);
  413. ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
  414. }
  415. return 1;
  416. }
  417. p = tmpdat;
  418. /* Doing sort: build up a list of each member's DER encoding */
  419. for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
  420. skitem = sk_ASN1_VALUE_value(sk, i);
  421. tder->data = p;
  422. tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
  423. tder->field = skitem;
  424. }
  425. /* Now sort them */
  426. qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
  427. /* Output sorted DER encoding */
  428. p = *out;
  429. for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
  430. memcpy(p, tder->data, tder->length);
  431. p += tder->length;
  432. }
  433. *out = p;
  434. /* If do_sort is 2 then reorder the STACK */
  435. if (do_sort == 2) {
  436. for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
  437. (void)sk_ASN1_VALUE_set(sk, i, tder->field);
  438. }
  439. OPENSSL_free(derlst);
  440. OPENSSL_free(tmpdat);
  441. return 1;
  442. }
  443. static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
  444. const ASN1_ITEM *it, int tag, int aclass)
  445. {
  446. int len;
  447. int utype;
  448. int usetag;
  449. int ndef = 0;
  450. utype = it->utype;
  451. /*
  452. * Get length of content octets and maybe find out the underlying type.
  453. */
  454. len = asn1_ex_i2c(pval, NULL, &utype, it);
  455. /*
  456. * If SEQUENCE, SET or OTHER then header is included in pseudo content
  457. * octets so don't include tag+length. We need to check here because the
  458. * call to asn1_ex_i2c() could change utype.
  459. */
  460. if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
  461. (utype == V_ASN1_OTHER))
  462. usetag = 0;
  463. else
  464. usetag = 1;
  465. /* -1 means omit type */
  466. if (len == -1)
  467. return 0;
  468. /* -2 return is special meaning use ndef */
  469. if (len == -2) {
  470. ndef = 2;
  471. len = 0;
  472. }
  473. /* If not implicitly tagged get tag from underlying type */
  474. if (tag == -1)
  475. tag = utype;
  476. /* Output tag+length followed by content octets */
  477. if (out) {
  478. if (usetag)
  479. ASN1_put_object(out, ndef, len, tag, aclass);
  480. asn1_ex_i2c(pval, *out, &utype, it);
  481. if (ndef)
  482. ASN1_put_eoc(out);
  483. else
  484. *out += len;
  485. }
  486. if (usetag)
  487. return ASN1_object_size(ndef, len, tag);
  488. return len;
  489. }
  490. /* Produce content octets from a structure */
  491. int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
  492. const ASN1_ITEM *it)
  493. {
  494. ASN1_BOOLEAN *tbool = NULL;
  495. ASN1_STRING *strtmp;
  496. ASN1_OBJECT *otmp;
  497. int utype;
  498. const unsigned char *cont;
  499. unsigned char c;
  500. int len;
  501. const ASN1_PRIMITIVE_FUNCS *pf;
  502. pf = it->funcs;
  503. if (pf && pf->prim_i2c)
  504. return pf->prim_i2c(pval, cout, putype, it);
  505. /* Should type be omitted? */
  506. if ((it->itype != ASN1_ITYPE_PRIMITIVE)
  507. || (it->utype != V_ASN1_BOOLEAN)) {
  508. if (!*pval)
  509. return -1;
  510. }
  511. if (it->itype == ASN1_ITYPE_MSTRING) {
  512. /* If MSTRING type set the underlying type */
  513. strtmp = (ASN1_STRING *)*pval;
  514. utype = strtmp->type;
  515. *putype = utype;
  516. } else if (it->utype == V_ASN1_ANY) {
  517. /* If ANY set type and pointer to value */
  518. ASN1_TYPE *typ;
  519. typ = (ASN1_TYPE *)*pval;
  520. utype = typ->type;
  521. *putype = utype;
  522. pval = &typ->value.asn1_value;
  523. } else
  524. utype = *putype;
  525. switch (utype) {
  526. case V_ASN1_OBJECT:
  527. otmp = (ASN1_OBJECT *)*pval;
  528. cont = otmp->data;
  529. len = otmp->length;
  530. break;
  531. case V_ASN1_NULL:
  532. cont = NULL;
  533. len = 0;
  534. break;
  535. case V_ASN1_BOOLEAN:
  536. tbool = (ASN1_BOOLEAN *)pval;
  537. if (*tbool == -1)
  538. return -1;
  539. if (it->utype != V_ASN1_ANY) {
  540. /*
  541. * Default handling if value == size field then omit
  542. */
  543. if (*tbool && (it->size > 0))
  544. return -1;
  545. if (!*tbool && !it->size)
  546. return -1;
  547. }
  548. c = (unsigned char)*tbool;
  549. cont = &c;
  550. len = 1;
  551. break;
  552. case V_ASN1_BIT_STRING:
  553. return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
  554. cout ? &cout : NULL);
  555. break;
  556. case V_ASN1_INTEGER:
  557. case V_ASN1_ENUMERATED:
  558. /*
  559. * These are all have the same content format as ASN1_INTEGER
  560. */
  561. return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
  562. break;
  563. case V_ASN1_OCTET_STRING:
  564. case V_ASN1_NUMERICSTRING:
  565. case V_ASN1_PRINTABLESTRING:
  566. case V_ASN1_T61STRING:
  567. case V_ASN1_VIDEOTEXSTRING:
  568. case V_ASN1_IA5STRING:
  569. case V_ASN1_UTCTIME:
  570. case V_ASN1_GENERALIZEDTIME:
  571. case V_ASN1_GRAPHICSTRING:
  572. case V_ASN1_VISIBLESTRING:
  573. case V_ASN1_GENERALSTRING:
  574. case V_ASN1_UNIVERSALSTRING:
  575. case V_ASN1_BMPSTRING:
  576. case V_ASN1_UTF8STRING:
  577. case V_ASN1_SEQUENCE:
  578. case V_ASN1_SET:
  579. default:
  580. /* All based on ASN1_STRING and handled the same */
  581. strtmp = (ASN1_STRING *)*pval;
  582. /* Special handling for NDEF */
  583. if ((it->size == ASN1_TFLG_NDEF)
  584. && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
  585. if (cout) {
  586. strtmp->data = cout;
  587. strtmp->length = 0;
  588. }
  589. /* Special return code */
  590. return -2;
  591. }
  592. cont = strtmp->data;
  593. len = strtmp->length;
  594. break;
  595. }
  596. if (cout && len)
  597. memcpy(cout, cont, len);
  598. return len;
  599. }