derdec.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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. static PRUint32
  7. der_indefinite_length(unsigned char *buf, unsigned char *end)
  8. {
  9. PRUint32 len, ret, dataLen;
  10. unsigned char tag, lenCode;
  11. int dataLenLen;
  12. len = 0;
  13. while (1) {
  14. if ((buf + 2) > end) {
  15. return (0);
  16. }
  17. tag = *buf++;
  18. lenCode = *buf++;
  19. len += 2;
  20. if ((tag == 0) && (lenCode == 0)) {
  21. return (len);
  22. }
  23. if (lenCode == 0x80) { /* indefinite length */
  24. ret = der_indefinite_length(buf, end); /* recurse to find length */
  25. if (ret == 0)
  26. return 0;
  27. len += ret;
  28. buf += ret;
  29. } else { /* definite length */
  30. if (lenCode & 0x80) {
  31. /* Length of data is in multibyte format */
  32. dataLenLen = lenCode & 0x7f;
  33. switch (dataLenLen) {
  34. case 1:
  35. dataLen = buf[0];
  36. break;
  37. case 2:
  38. dataLen = (buf[0] << 8) | buf[1];
  39. break;
  40. case 3:
  41. dataLen = ((unsigned long)buf[0] << 16) | (buf[1] << 8) | buf[2];
  42. break;
  43. case 4:
  44. dataLen = ((unsigned long)buf[0] << 24) |
  45. ((unsigned long)buf[1] << 16) | (buf[2] << 8) | buf[3];
  46. break;
  47. default:
  48. PORT_SetError(SEC_ERROR_BAD_DER);
  49. return SECFailure;
  50. }
  51. } else {
  52. /* Length of data is in single byte */
  53. dataLen = lenCode;
  54. dataLenLen = 0;
  55. }
  56. /* skip this item */
  57. buf = buf + dataLenLen + dataLen;
  58. len = len + dataLenLen + dataLen;
  59. }
  60. }
  61. }
  62. /*
  63. ** Capture the next thing in the buffer.
  64. ** Returns the length of the header and the length of the contents.
  65. */
  66. static SECStatus
  67. der_capture(unsigned char *buf, unsigned char *end,
  68. int *header_len_p, PRUint32 *contents_len_p)
  69. {
  70. unsigned char *bp;
  71. unsigned char whole_tag;
  72. PRUint32 contents_len;
  73. int tag_number;
  74. if ((buf + 2) > end) {
  75. *header_len_p = 0;
  76. *contents_len_p = 0;
  77. if (buf == end)
  78. return SECSuccess;
  79. return SECFailure;
  80. }
  81. bp = buf;
  82. /* Get tag and verify that it is ok. */
  83. whole_tag = *bp++;
  84. tag_number = whole_tag & DER_TAGNUM_MASK;
  85. /*
  86. * XXX This code does not (yet) handle the high-tag-number form!
  87. */
  88. if (tag_number == DER_HIGH_TAG_NUMBER) {
  89. PORT_SetError(SEC_ERROR_BAD_DER);
  90. return SECFailure;
  91. }
  92. if ((whole_tag & DER_CLASS_MASK) == DER_UNIVERSAL) {
  93. /* Check that the universal tag number is one we implement. */
  94. switch (tag_number) {
  95. case DER_BOOLEAN:
  96. case DER_INTEGER:
  97. case DER_BIT_STRING:
  98. case DER_OCTET_STRING:
  99. case DER_NULL:
  100. case DER_OBJECT_ID:
  101. case DER_SEQUENCE:
  102. case DER_SET:
  103. case DER_PRINTABLE_STRING:
  104. case DER_T61_STRING:
  105. case DER_IA5_STRING:
  106. case DER_VISIBLE_STRING:
  107. case DER_UTC_TIME:
  108. case 0: /* end-of-contents tag */
  109. break;
  110. default:
  111. PORT_SetError(SEC_ERROR_BAD_DER);
  112. return SECFailure;
  113. }
  114. }
  115. /*
  116. * Get first byte of length code (might contain entire length, might not).
  117. */
  118. contents_len = *bp++;
  119. /*
  120. * If the high bit is set, then the length is in multibyte format,
  121. * or the thing has an indefinite-length.
  122. */
  123. if (contents_len & 0x80) {
  124. int bytes_of_encoded_len;
  125. bytes_of_encoded_len = contents_len & 0x7f;
  126. contents_len = 0;
  127. switch (bytes_of_encoded_len) {
  128. case 4:
  129. contents_len |= *bp++;
  130. contents_len <<= 8;
  131. /* fallthru */
  132. case 3:
  133. contents_len |= *bp++;
  134. contents_len <<= 8;
  135. /* fallthru */
  136. case 2:
  137. contents_len |= *bp++;
  138. contents_len <<= 8;
  139. /* fallthru */
  140. case 1:
  141. contents_len |= *bp++;
  142. break;
  143. case 0:
  144. contents_len = der_indefinite_length(bp, end);
  145. if (contents_len)
  146. break;
  147. /* fallthru */
  148. default:
  149. PORT_SetError(SEC_ERROR_BAD_DER);
  150. return SECFailure;
  151. }
  152. }
  153. if ((bp + contents_len) > end) {
  154. /* Ran past end of buffer */
  155. PORT_SetError(SEC_ERROR_BAD_DER);
  156. return SECFailure;
  157. }
  158. *header_len_p = (int)(bp - buf);
  159. *contents_len_p = contents_len;
  160. return SECSuccess;
  161. }
  162. SECStatus
  163. DER_Lengths(SECItem *item, int *header_len_p, PRUint32 *contents_len_p)
  164. {
  165. return (der_capture(item->data, &item->data[item->len], header_len_p,
  166. contents_len_p));
  167. }