dersubr.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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 <limits.h>
  6. #include "secerr.h"
  7. int
  8. DER_LengthLength(PRUint32 len)
  9. {
  10. if (len > 127) {
  11. if (len > 255) {
  12. if (len > 65535L) {
  13. if (len > 16777215L) {
  14. return 5;
  15. } else {
  16. return 4;
  17. }
  18. } else {
  19. return 3;
  20. }
  21. } else {
  22. return 2;
  23. }
  24. } else {
  25. return 1;
  26. }
  27. }
  28. unsigned char *
  29. DER_StoreHeader(unsigned char *buf, unsigned int code, PRUint32 len)
  30. {
  31. unsigned char b[4];
  32. b[0] = (unsigned char)(len >> 24);
  33. b[1] = (unsigned char)(len >> 16);
  34. b[2] = (unsigned char)(len >> 8);
  35. b[3] = (unsigned char)len;
  36. if ((code & DER_TAGNUM_MASK) == DER_SET || (code & DER_TAGNUM_MASK) == DER_SEQUENCE)
  37. code |= DER_CONSTRUCTED;
  38. *buf++ = code;
  39. if (len > 127) {
  40. if (len > 255) {
  41. if (len > 65535) {
  42. if (len > 16777215) {
  43. *buf++ = 0x84;
  44. *buf++ = b[0];
  45. *buf++ = b[1];
  46. *buf++ = b[2];
  47. *buf++ = b[3];
  48. } else {
  49. *buf++ = 0x83;
  50. *buf++ = b[1];
  51. *buf++ = b[2];
  52. *buf++ = b[3];
  53. }
  54. } else {
  55. *buf++ = 0x82;
  56. *buf++ = b[2];
  57. *buf++ = b[3];
  58. }
  59. } else {
  60. *buf++ = 0x81;
  61. *buf++ = b[3];
  62. }
  63. } else {
  64. *buf++ = b[3];
  65. }
  66. return buf;
  67. }
  68. /*
  69. * XXX This should be rewritten, generalized, to take a long instead
  70. * of a PRInt32.
  71. */
  72. SECStatus
  73. DER_SetInteger(PLArenaPool *arena, SECItem *it, PRInt32 i)
  74. {
  75. unsigned char bb[4];
  76. unsigned len;
  77. bb[0] = (unsigned char)(i >> 24);
  78. bb[1] = (unsigned char)(i >> 16);
  79. bb[2] = (unsigned char)(i >> 8);
  80. bb[3] = (unsigned char)(i);
  81. /*
  82. ** Small integers are encoded in a single byte. Larger integers
  83. ** require progressively more space.
  84. */
  85. if (i < -128) {
  86. if (i < -32768L) {
  87. if (i < -8388608L) {
  88. len = 4;
  89. } else {
  90. len = 3;
  91. }
  92. } else {
  93. len = 2;
  94. }
  95. } else if (i > 127) {
  96. if (i > 32767L) {
  97. if (i > 8388607L) {
  98. len = 4;
  99. } else {
  100. len = 3;
  101. }
  102. } else {
  103. len = 2;
  104. }
  105. } else {
  106. len = 1;
  107. }
  108. it->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
  109. if (!it->data) {
  110. return SECFailure;
  111. }
  112. it->len = len;
  113. PORT_Memcpy(it->data, bb + (4 - len), len);
  114. return SECSuccess;
  115. }
  116. /*
  117. * XXX This should be rewritten, generalized, to take an unsigned long instead
  118. * of a PRUint32.
  119. */
  120. SECStatus
  121. DER_SetUInteger(PLArenaPool *arena, SECItem *it, PRUint32 ui)
  122. {
  123. unsigned char bb[5];
  124. int len;
  125. bb[0] = 0;
  126. bb[1] = (unsigned char)(ui >> 24);
  127. bb[2] = (unsigned char)(ui >> 16);
  128. bb[3] = (unsigned char)(ui >> 8);
  129. bb[4] = (unsigned char)(ui);
  130. /*
  131. ** Small integers are encoded in a single byte. Larger integers
  132. ** require progressively more space.
  133. */
  134. if (ui > 0x7f) {
  135. if (ui > 0x7fff) {
  136. if (ui > 0x7fffffL) {
  137. if (ui >= 0x80000000L) {
  138. len = 5;
  139. } else {
  140. len = 4;
  141. }
  142. } else {
  143. len = 3;
  144. }
  145. } else {
  146. len = 2;
  147. }
  148. } else {
  149. len = 1;
  150. }
  151. it->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
  152. if (it->data == NULL) {
  153. return SECFailure;
  154. }
  155. it->len = len;
  156. PORT_Memcpy(it->data, bb + (sizeof(bb) - len), len);
  157. return SECSuccess;
  158. }
  159. /*
  160. ** Convert a der encoded *signed* integer into a machine integral value.
  161. ** If an underflow/overflow occurs, sets error code and returns min/max.
  162. */
  163. long
  164. DER_GetInteger(const SECItem *it)
  165. {
  166. unsigned long ival;
  167. PRBool negative;
  168. unsigned int len = it->len;
  169. unsigned char *cp = it->data;
  170. size_t lsize = sizeof(ival);
  171. PORT_Assert(len);
  172. if (!len) {
  173. PORT_SetError(SEC_ERROR_INPUT_LEN);
  174. return 0;
  175. }
  176. negative = (PRBool)(*cp & 0x80);
  177. ival = negative ? ~0 : 0;
  178. /* Ignore leading zeros/ones. */
  179. while (len && *cp == (unsigned char)ival) {
  180. len--;
  181. cp++;
  182. }
  183. /* Check for overflow/underflow. */
  184. if (len > lsize || (len == lsize && (*cp & 0x80) != negative)) {
  185. PORT_SetError(SEC_ERROR_BAD_DER);
  186. return negative ? LONG_MIN : LONG_MAX;
  187. }
  188. while (len--) {
  189. ival <<= 8;
  190. ival |= *cp++;
  191. }
  192. return ival;
  193. }
  194. /*
  195. ** Convert a der encoded *unsigned* integer into a machine integral value.
  196. ** If an overflow occurs, sets error code and returns max.
  197. */
  198. unsigned long
  199. DER_GetUInteger(SECItem *it)
  200. {
  201. unsigned long ival = 0;
  202. unsigned len = it->len;
  203. unsigned char *cp = it->data;
  204. unsigned long overflow = 0xffUL << ((sizeof(ival) - 1) * 8);
  205. PORT_Assert(len);
  206. if (!len) {
  207. PORT_SetError(SEC_ERROR_INPUT_LEN);
  208. return 0;
  209. }
  210. /* Cannot put a negative value into an unsigned container. */
  211. if (*cp & 0x80) {
  212. PORT_SetError(SEC_ERROR_BAD_DER);
  213. return 0;
  214. }
  215. while (len) {
  216. if (ival & overflow) {
  217. PORT_SetError(SEC_ERROR_BAD_DER);
  218. return ULONG_MAX;
  219. }
  220. ival = ival << 8;
  221. ival |= *cp++;
  222. --len;
  223. }
  224. return ival;
  225. }