derenc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "secder.h"
  5. #include "secerr.h"
  6. #if 0
  7. /*
  8. * Generic templates for individual/simple items.
  9. */
  10. DERTemplate SECAnyTemplate[] = {
  11. { DER_ANY,
  12. 0, NULL, sizeof(SECItem) }
  13. };
  14. DERTemplate SECBitStringTemplate[] = {
  15. { DER_BIT_STRING,
  16. 0, NULL, sizeof(SECItem) }
  17. };
  18. DERTemplate SECBooleanTemplate[] = {
  19. { DER_BOOLEAN,
  20. 0, NULL, sizeof(SECItem) }
  21. };
  22. DERTemplate SECIA5StringTemplate[] = {
  23. { DER_IA5_STRING,
  24. 0, NULL, sizeof(SECItem) }
  25. };
  26. DERTemplate SECIntegerTemplate[] = {
  27. { DER_INTEGER,
  28. 0, NULL, sizeof(SECItem) }
  29. };
  30. DERTemplate SECNullTemplate[] = {
  31. { DER_NULL,
  32. 0, NULL, sizeof(SECItem) }
  33. };
  34. DERTemplate SECObjectIDTemplate[] = {
  35. { DER_OBJECT_ID,
  36. 0, NULL, sizeof(SECItem) }
  37. };
  38. DERTemplate SECOctetStringTemplate[] = {
  39. { DER_OCTET_STRING,
  40. 0, NULL, sizeof(SECItem) }
  41. };
  42. DERTemplate SECPrintableStringTemplate[] = {
  43. { DER_PRINTABLE_STRING,
  44. 0, NULL, sizeof(SECItem) }
  45. };
  46. DERTemplate SECT61StringTemplate[] = {
  47. { DER_T61_STRING,
  48. 0, NULL, sizeof(SECItem) }
  49. };
  50. DERTemplate SECUTCTimeTemplate[] = {
  51. { DER_UTC_TIME,
  52. 0, NULL, sizeof(SECItem) }
  53. };
  54. #endif
  55. static int
  56. header_length(DERTemplate *dtemplate, PRUint32 contents_len)
  57. {
  58. PRUint32 len;
  59. unsigned long encode_kind, under_kind;
  60. PRBool explicit, optional, universal;
  61. encode_kind = dtemplate->kind;
  62. explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE;
  63. optional = (encode_kind & DER_OPTIONAL) ? PR_TRUE : PR_FALSE;
  64. universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
  65. ? PR_TRUE
  66. : PR_FALSE;
  67. PORT_Assert(!(explicit && universal)); /* bad templates */
  68. if (encode_kind & DER_POINTER) {
  69. if (dtemplate->sub != NULL) {
  70. under_kind = dtemplate->sub->kind;
  71. if (universal) {
  72. encode_kind = under_kind;
  73. }
  74. } else if (universal) {
  75. under_kind = encode_kind & ~DER_POINTER;
  76. } else {
  77. under_kind = dtemplate->arg;
  78. }
  79. } else if (encode_kind & DER_INLINE) {
  80. PORT_Assert(dtemplate->sub != NULL);
  81. under_kind = dtemplate->sub->kind;
  82. if (universal) {
  83. encode_kind = under_kind;
  84. }
  85. } else if (universal) {
  86. under_kind = encode_kind;
  87. } else {
  88. under_kind = dtemplate->arg;
  89. }
  90. /* This is only used in decoding; it plays no part in encoding. */
  91. if (under_kind & DER_DERPTR)
  92. return 0;
  93. /* No header at all for an "empty" optional. */
  94. if ((contents_len == 0) && optional)
  95. return 0;
  96. /* And no header for a full DER_ANY. */
  97. if (encode_kind & DER_ANY)
  98. return 0;
  99. /*
  100. * The common case: one octet for identifier and as many octets
  101. * as necessary to hold the content length.
  102. */
  103. len = 1 + DER_LengthLength(contents_len);
  104. /* Account for the explicit wrapper, if necessary. */
  105. if (explicit) {
  106. #if 0 /* \
  107. * Well, I was trying to do something useful, but these \
  108. * assertions are too restrictive on valid templates. \
  109. * I wanted to make sure that the top-level "kind" of \
  110. * a template does not also specify DER_EXPLICIT, which \
  111. * should only modify a component field. Maybe later \
  112. * I can figure out a better way to detect such a problem, \
  113. * but for now I must remove these checks altogether. \
  114. */
  115. /*
  116. * This modifier applies only to components of a set or sequence;
  117. * it should never be used on a set/sequence itself -- confirm.
  118. */
  119. PORT_Assert (under_kind != DER_SEQUENCE);
  120. PORT_Assert (under_kind != DER_SET);
  121. #endif
  122. len += 1 + DER_LengthLength(len + contents_len);
  123. }
  124. return len;
  125. }
  126. static PRUint32
  127. contents_length(DERTemplate *dtemplate, void *src)
  128. {
  129. PRUint32 len;
  130. unsigned long encode_kind, under_kind;
  131. PRBool universal;
  132. PORT_Assert(src != NULL);
  133. encode_kind = dtemplate->kind;
  134. universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
  135. ? PR_TRUE
  136. : PR_FALSE;
  137. encode_kind &= ~DER_OPTIONAL;
  138. if (encode_kind & DER_POINTER) {
  139. src = *(void **)src;
  140. if (src == NULL) {
  141. return 0;
  142. }
  143. if (dtemplate->sub != NULL) {
  144. dtemplate = dtemplate->sub;
  145. under_kind = dtemplate->kind;
  146. src = (void *)((char *)src + dtemplate->offset);
  147. } else if (universal) {
  148. under_kind = encode_kind & ~DER_POINTER;
  149. } else {
  150. under_kind = dtemplate->arg;
  151. }
  152. } else if (encode_kind & DER_INLINE) {
  153. PORT_Assert(dtemplate->sub != NULL);
  154. dtemplate = dtemplate->sub;
  155. under_kind = dtemplate->kind;
  156. src = (void *)((char *)src + dtemplate->offset);
  157. } else if (universal) {
  158. under_kind = encode_kind;
  159. } else {
  160. under_kind = dtemplate->arg;
  161. }
  162. /* Having any of these bits is not expected here... */
  163. PORT_Assert((under_kind & (DER_EXPLICIT | DER_INLINE | DER_OPTIONAL | DER_POINTER | DER_SKIP)) == 0);
  164. /* This is only used in decoding; it plays no part in encoding. */
  165. if (under_kind & DER_DERPTR)
  166. return 0;
  167. if (under_kind & DER_INDEFINITE) {
  168. PRUint32 sub_len;
  169. void **indp = *(void ***)src;
  170. if (indp == NULL)
  171. return 0;
  172. len = 0;
  173. under_kind &= ~DER_INDEFINITE;
  174. if (under_kind == DER_SET || under_kind == DER_SEQUENCE) {
  175. DERTemplate *tmpt = dtemplate->sub;
  176. PORT_Assert(tmpt != NULL);
  177. for (; *indp != NULL; indp++) {
  178. void *sub_src = (void *)((char *)(*indp) + tmpt->offset);
  179. sub_len = contents_length(tmpt, sub_src);
  180. len += sub_len + header_length(tmpt, sub_len);
  181. }
  182. } else {
  183. /*
  184. * XXX Lisa is not sure this code (for handling, for example,
  185. * DER_INDEFINITE | DER_OCTET_STRING) is right.
  186. */
  187. for (; *indp != NULL; indp++) {
  188. SECItem *item = (SECItem *)(*indp);
  189. sub_len = item->len;
  190. if (under_kind == DER_BIT_STRING) {
  191. sub_len = (sub_len + 7) >> 3;
  192. /* bit string contents involve an extra octet */
  193. if (sub_len)
  194. sub_len++;
  195. }
  196. if (under_kind != DER_ANY)
  197. len += 1 + DER_LengthLength(sub_len);
  198. }
  199. }
  200. return len;
  201. }
  202. switch (under_kind) {
  203. case DER_SEQUENCE:
  204. case DER_SET: {
  205. DERTemplate *tmpt;
  206. void *sub_src;
  207. PRUint32 sub_len;
  208. len = 0;
  209. for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) {
  210. sub_src = (void *)((char *)src + tmpt->offset);
  211. sub_len = contents_length(tmpt, sub_src);
  212. len += sub_len + header_length(tmpt, sub_len);
  213. }
  214. } break;
  215. case DER_BIT_STRING:
  216. len = (((SECItem *)src)->len + 7) >> 3;
  217. /* bit string contents involve an extra octet */
  218. if (len)
  219. len++;
  220. break;
  221. default:
  222. len = ((SECItem *)src)->len;
  223. break;
  224. }
  225. return len;
  226. }
  227. static unsigned char *
  228. der_encode(unsigned char *buf, DERTemplate *dtemplate, void *src)
  229. {
  230. int header_len;
  231. PRUint32 contents_len;
  232. unsigned long encode_kind, under_kind;
  233. PRBool explicit, universal;
  234. /*
  235. * First figure out how long the encoding will be. Do this by
  236. * traversing the template from top to bottom and accumulating
  237. * the length of each leaf item.
  238. */
  239. contents_len = contents_length(dtemplate, src);
  240. header_len = header_length(dtemplate, contents_len);
  241. /*
  242. * Enough smarts was involved already, so that if both the
  243. * header and the contents have a length of zero, then we
  244. * are not doing any encoding for this element.
  245. */
  246. if (header_len == 0 && contents_len == 0)
  247. return buf;
  248. encode_kind = dtemplate->kind;
  249. explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE;
  250. encode_kind &= ~DER_OPTIONAL;
  251. universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
  252. ? PR_TRUE
  253. : PR_FALSE;
  254. if (encode_kind & DER_POINTER) {
  255. if (contents_len) {
  256. src = *(void **)src;
  257. PORT_Assert(src != NULL);
  258. }
  259. if (dtemplate->sub != NULL) {
  260. dtemplate = dtemplate->sub;
  261. under_kind = dtemplate->kind;
  262. if (universal) {
  263. encode_kind = under_kind;
  264. }
  265. src = (void *)((char *)src + dtemplate->offset);
  266. } else if (universal) {
  267. under_kind = encode_kind & ~DER_POINTER;
  268. } else {
  269. under_kind = dtemplate->arg;
  270. }
  271. } else if (encode_kind & DER_INLINE) {
  272. dtemplate = dtemplate->sub;
  273. under_kind = dtemplate->kind;
  274. if (universal) {
  275. encode_kind = under_kind;
  276. }
  277. src = (void *)((char *)src + dtemplate->offset);
  278. } else if (universal) {
  279. under_kind = encode_kind;
  280. } else {
  281. under_kind = dtemplate->arg;
  282. }
  283. if (explicit) {
  284. buf = DER_StoreHeader(buf, encode_kind,
  285. (1 + DER_LengthLength(contents_len) + contents_len));
  286. encode_kind = under_kind;
  287. }
  288. if ((encode_kind & DER_ANY) == 0) { /* DER_ANY already contains header */
  289. buf = DER_StoreHeader(buf, encode_kind, contents_len);
  290. }
  291. /* If no real contents to encode, then we are done. */
  292. if (contents_len == 0)
  293. return buf;
  294. if (under_kind & DER_INDEFINITE) {
  295. void **indp;
  296. indp = *(void ***)src;
  297. PORT_Assert(indp != NULL);
  298. under_kind &= ~DER_INDEFINITE;
  299. if (under_kind == DER_SET || under_kind == DER_SEQUENCE) {
  300. DERTemplate *tmpt = dtemplate->sub;
  301. PORT_Assert(tmpt != NULL);
  302. for (; *indp != NULL; indp++) {
  303. void *sub_src = (void *)((char *)(*indp) + tmpt->offset);
  304. buf = der_encode(buf, tmpt, sub_src);
  305. }
  306. } else {
  307. for (; *indp != NULL; indp++) {
  308. SECItem *item;
  309. int sub_len;
  310. item = (SECItem *)(*indp);
  311. sub_len = item->len;
  312. if (under_kind == DER_BIT_STRING) {
  313. if (sub_len) {
  314. int rem;
  315. sub_len = (sub_len + 7) >> 3;
  316. buf = DER_StoreHeader(buf, under_kind, sub_len + 1);
  317. rem = (sub_len << 3) - item->len;
  318. *buf++ = rem; /* remaining bits */
  319. } else {
  320. buf = DER_StoreHeader(buf, under_kind, 0);
  321. }
  322. } else if (under_kind != DER_ANY) {
  323. buf = DER_StoreHeader(buf, under_kind, sub_len);
  324. }
  325. PORT_Memcpy(buf, item->data, sub_len);
  326. buf += sub_len;
  327. }
  328. }
  329. return buf;
  330. }
  331. switch (under_kind) {
  332. case DER_SEQUENCE:
  333. case DER_SET: {
  334. DERTemplate *tmpt;
  335. void *sub_src;
  336. for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) {
  337. sub_src = (void *)((char *)src + tmpt->offset);
  338. buf = der_encode(buf, tmpt, sub_src);
  339. }
  340. } break;
  341. case DER_BIT_STRING: {
  342. SECItem *item;
  343. int rem;
  344. /*
  345. * The contents length includes our extra octet; subtract
  346. * it off so we just have the real string length there.
  347. */
  348. contents_len--;
  349. item = (SECItem *)src;
  350. PORT_Assert(contents_len == ((item->len + 7) >> 3));
  351. rem = (contents_len << 3) - item->len;
  352. *buf++ = rem; /* remaining bits */
  353. PORT_Memcpy(buf, item->data, contents_len);
  354. buf += contents_len;
  355. } break;
  356. default: {
  357. SECItem *item;
  358. item = (SECItem *)src;
  359. PORT_Assert(contents_len == item->len);
  360. PORT_Memcpy(buf, item->data, contents_len);
  361. buf += contents_len;
  362. } break;
  363. }
  364. return buf;
  365. }
  366. SECStatus
  367. DER_Encode(PLArenaPool *arena, SECItem *dest, DERTemplate *dtemplate, void *src)
  368. {
  369. unsigned int contents_len, header_len;
  370. src = (void **)((char *)src + dtemplate->offset);
  371. /*
  372. * First figure out how long the encoding will be. Do this by
  373. * traversing the template from top to bottom and accumulating
  374. * the length of each leaf item.
  375. */
  376. contents_len = contents_length(dtemplate, src);
  377. header_len = header_length(dtemplate, contents_len);
  378. dest->len = contents_len + header_len;
  379. /* Allocate storage to hold the encoding */
  380. dest->data = (unsigned char *)PORT_ArenaAlloc(arena, dest->len);
  381. if (dest->data == NULL) {
  382. PORT_SetError(SEC_ERROR_NO_MEMORY);
  383. return SECFailure;
  384. }
  385. /* Now encode into the buffer */
  386. (void)der_encode(dest->data, dtemplate, src);
  387. return SECSuccess;
  388. }