/security/nss/lib/util/secitem.c

http://github.com/zpao/v8monkey · C · 328 lines · 227 code · 33 blank · 68 comment · 91 complexity · 81cfe4e57fac082167bc2774e4d8ac5a MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. *
  23. * Alternatively, the contents of this file may be used under the terms of
  24. * either the GNU General Public License Version 2 or later (the "GPL"), or
  25. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26. * in which case the provisions of the GPL or the LGPL are applicable instead
  27. * of those above. If you wish to allow use of your version of this file only
  28. * under the terms of either the GPL or the LGPL, and not to allow others to
  29. * use your version of this file under the terms of the MPL, indicate your
  30. * decision by deleting the provisions above and replace them with the notice
  31. * and other provisions required by the GPL or the LGPL. If you do not delete
  32. * the provisions above, a recipient may use your version of this file under
  33. * the terms of any one of the MPL, the GPL or the LGPL.
  34. *
  35. * ***** END LICENSE BLOCK ***** */
  36. /*
  37. * Support routines for SECItem data structure.
  38. *
  39. * $Id: secitem.c,v 1.16 2011/07/22 21:22:40 wtc%google.com Exp $
  40. */
  41. #include "seccomon.h"
  42. #include "secitem.h"
  43. #include "base64.h"
  44. #include "secerr.h"
  45. SECItem *
  46. SECITEM_AllocItem(PRArenaPool *arena, SECItem *item, unsigned int len)
  47. {
  48. SECItem *result = NULL;
  49. void *mark = NULL;
  50. if (arena != NULL) {
  51. mark = PORT_ArenaMark(arena);
  52. }
  53. if (item == NULL) {
  54. if (arena != NULL) {
  55. result = PORT_ArenaZAlloc(arena, sizeof(SECItem));
  56. } else {
  57. result = PORT_ZAlloc(sizeof(SECItem));
  58. }
  59. if (result == NULL) {
  60. goto loser;
  61. }
  62. } else {
  63. PORT_Assert(item->data == NULL);
  64. result = item;
  65. }
  66. result->len = len;
  67. if (len) {
  68. if (arena != NULL) {
  69. result->data = PORT_ArenaAlloc(arena, len);
  70. } else {
  71. result->data = PORT_Alloc(len);
  72. }
  73. if (result->data == NULL) {
  74. goto loser;
  75. }
  76. } else {
  77. result->data = NULL;
  78. }
  79. if (mark) {
  80. PORT_ArenaUnmark(arena, mark);
  81. }
  82. return(result);
  83. loser:
  84. if ( arena != NULL ) {
  85. if (mark) {
  86. PORT_ArenaRelease(arena, mark);
  87. }
  88. if (item != NULL) {
  89. item->data = NULL;
  90. item->len = 0;
  91. }
  92. } else {
  93. if (result != NULL) {
  94. SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE);
  95. }
  96. /*
  97. * If item is not NULL, the above has set item->data and
  98. * item->len to 0.
  99. */
  100. }
  101. return(NULL);
  102. }
  103. SECStatus
  104. SECITEM_ReallocItem(PRArenaPool *arena, SECItem *item, unsigned int oldlen,
  105. unsigned int newlen)
  106. {
  107. PORT_Assert(item != NULL);
  108. if (item == NULL) {
  109. /* XXX Set error. But to what? */
  110. return SECFailure;
  111. }
  112. /*
  113. * If no old length, degenerate to just plain alloc.
  114. */
  115. if (oldlen == 0) {
  116. PORT_Assert(item->data == NULL || item->len == 0);
  117. if (newlen == 0) {
  118. /* Nothing to do. Weird, but not a failure. */
  119. return SECSuccess;
  120. }
  121. item->len = newlen;
  122. if (arena != NULL) {
  123. item->data = PORT_ArenaAlloc(arena, newlen);
  124. } else {
  125. item->data = PORT_Alloc(newlen);
  126. }
  127. } else {
  128. if (arena != NULL) {
  129. item->data = PORT_ArenaGrow(arena, item->data, oldlen, newlen);
  130. } else {
  131. item->data = PORT_Realloc(item->data, newlen);
  132. }
  133. }
  134. if (item->data == NULL) {
  135. return SECFailure;
  136. }
  137. return SECSuccess;
  138. }
  139. SECComparison
  140. SECITEM_CompareItem(const SECItem *a, const SECItem *b)
  141. {
  142. unsigned m;
  143. SECComparison rv;
  144. if (a == b)
  145. return SECEqual;
  146. if (!a || !a->len || !a->data)
  147. return (!b || !b->len || !b->data) ? SECEqual : SECLessThan;
  148. if (!b || !b->len || !b->data)
  149. return SECGreaterThan;
  150. m = ( ( a->len < b->len ) ? a->len : b->len );
  151. rv = (SECComparison) PORT_Memcmp(a->data, b->data, m);
  152. if (rv) {
  153. return rv;
  154. }
  155. if (a->len < b->len) {
  156. return SECLessThan;
  157. }
  158. if (a->len == b->len) {
  159. return SECEqual;
  160. }
  161. return SECGreaterThan;
  162. }
  163. PRBool
  164. SECITEM_ItemsAreEqual(const SECItem *a, const SECItem *b)
  165. {
  166. if (a->len != b->len)
  167. return PR_FALSE;
  168. if (!a->len)
  169. return PR_TRUE;
  170. if (!a->data || !b->data) {
  171. /* avoid null pointer crash. */
  172. return (PRBool)(a->data == b->data);
  173. }
  174. return (PRBool)!PORT_Memcmp(a->data, b->data, a->len);
  175. }
  176. SECItem *
  177. SECITEM_DupItem(const SECItem *from)
  178. {
  179. return SECITEM_ArenaDupItem(NULL, from);
  180. }
  181. SECItem *
  182. SECITEM_ArenaDupItem(PRArenaPool *arena, const SECItem *from)
  183. {
  184. SECItem *to;
  185. if ( from == NULL ) {
  186. return(NULL);
  187. }
  188. if ( arena != NULL ) {
  189. to = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem));
  190. } else {
  191. to = (SECItem *)PORT_Alloc(sizeof(SECItem));
  192. }
  193. if ( to == NULL ) {
  194. return(NULL);
  195. }
  196. if ( arena != NULL ) {
  197. to->data = (unsigned char *)PORT_ArenaAlloc(arena, from->len);
  198. } else {
  199. to->data = (unsigned char *)PORT_Alloc(from->len);
  200. }
  201. if ( to->data == NULL ) {
  202. PORT_Free(to);
  203. return(NULL);
  204. }
  205. to->len = from->len;
  206. to->type = from->type;
  207. if ( to->len ) {
  208. PORT_Memcpy(to->data, from->data, to->len);
  209. }
  210. return(to);
  211. }
  212. SECStatus
  213. SECITEM_CopyItem(PRArenaPool *arena, SECItem *to, const SECItem *from)
  214. {
  215. to->type = from->type;
  216. if (from->data && from->len) {
  217. if ( arena ) {
  218. to->data = (unsigned char*) PORT_ArenaAlloc(arena, from->len);
  219. } else {
  220. to->data = (unsigned char*) PORT_Alloc(from->len);
  221. }
  222. if (!to->data) {
  223. return SECFailure;
  224. }
  225. PORT_Memcpy(to->data, from->data, from->len);
  226. to->len = from->len;
  227. } else {
  228. /*
  229. * If from->data is NULL but from->len is nonzero, this function
  230. * will succeed. Is this right?
  231. */
  232. to->data = 0;
  233. to->len = 0;
  234. }
  235. return SECSuccess;
  236. }
  237. void
  238. SECITEM_FreeItem(SECItem *zap, PRBool freeit)
  239. {
  240. if (zap) {
  241. PORT_Free(zap->data);
  242. zap->data = 0;
  243. zap->len = 0;
  244. if (freeit) {
  245. PORT_Free(zap);
  246. }
  247. }
  248. }
  249. void
  250. SECITEM_ZfreeItem(SECItem *zap, PRBool freeit)
  251. {
  252. if (zap) {
  253. PORT_ZFree(zap->data, zap->len);
  254. zap->data = 0;
  255. zap->len = 0;
  256. if (freeit) {
  257. PORT_ZFree(zap, sizeof(SECItem));
  258. }
  259. }
  260. }
  261. /* these reroutines were taken from pkix oid.c, which is supposed to
  262. * replace this file some day */
  263. /*
  264. * This is the hash function. We simply XOR the encoded form with
  265. * itself in sizeof(PLHashNumber)-byte chunks. Improving this
  266. * routine is left as an excercise for the more mathematically
  267. * inclined student.
  268. */
  269. PLHashNumber PR_CALLBACK
  270. SECITEM_Hash ( const void *key)
  271. {
  272. const SECItem *item = (const SECItem *)key;
  273. PLHashNumber rv = 0;
  274. PRUint8 *data = (PRUint8 *)item->data;
  275. PRUint32 i;
  276. PRUint8 *rvc = (PRUint8 *)&rv;
  277. for( i = 0; i < item->len; i++ ) {
  278. rvc[ i % sizeof(rv) ] ^= *data;
  279. data++;
  280. }
  281. return rv;
  282. }
  283. /*
  284. * This is the key-compare function. It simply does a lexical
  285. * comparison on the item data. This does not result in
  286. * quite the same ordering as the "sequence of numbers" order,
  287. * but heck it's only used internally by the hash table anyway.
  288. */
  289. PRIntn PR_CALLBACK
  290. SECITEM_HashCompare ( const void *k1, const void *k2)
  291. {
  292. const SECItem *i1 = (const SECItem *)k1;
  293. const SECItem *i2 = (const SECItem *)k2;
  294. return SECITEM_ItemsAreEqual(i1,i2);
  295. }