/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c

http://github.com/zpao/v8monkey · C · 431 lines · 243 code · 82 blank · 106 comment · 27 complexity · b8b8d53716b517c39c7709ee325eccea 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 PKIX-C library.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Sun Microsystems, Inc.
  18. * Portions created by the Initial Developer are
  19. * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Sun Microsystems, Inc.
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either the GNU General Public License Version 2 or later (the "GPL"), or
  26. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /*
  38. * pkix_pl_bigint.c
  39. *
  40. * BigInt Object Functions
  41. *
  42. */
  43. #include "pkix_pl_bigint.h"
  44. /* --Private-Big-Int-Functions------------------------------------ */
  45. /*
  46. * FUNCTION: pkix_pl_BigInt_Comparator
  47. * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
  48. */
  49. static PKIX_Error *
  50. pkix_pl_BigInt_Comparator(
  51. PKIX_PL_Object *firstObject,
  52. PKIX_PL_Object *secondObject,
  53. PKIX_Int32 *pResult,
  54. void *plContext)
  55. {
  56. PKIX_PL_BigInt *firstBigInt = NULL;
  57. PKIX_PL_BigInt *secondBigInt = NULL;
  58. char *firstPtr = NULL;
  59. char *secondPtr = NULL;
  60. PKIX_UInt32 firstLen, secondLen;
  61. PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Comparator");
  62. PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
  63. PKIX_CHECK(pkix_CheckTypes
  64. (firstObject, secondObject, PKIX_BIGINT_TYPE, plContext),
  65. PKIX_ARGUMENTSNOTBIGINTS);
  66. /* It's safe to cast */
  67. firstBigInt = (PKIX_PL_BigInt*)firstObject;
  68. secondBigInt = (PKIX_PL_BigInt*)secondObject;
  69. *pResult = 0;
  70. firstPtr = firstBigInt->dataRep;
  71. secondPtr = secondBigInt->dataRep;
  72. firstLen = firstBigInt->length;
  73. secondLen = secondBigInt->length;
  74. if (firstLen < secondLen) {
  75. *pResult = -1;
  76. } else if (firstLen > secondLen) {
  77. *pResult = 1;
  78. } else if (firstLen == secondLen) {
  79. PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcmp).\n");
  80. *pResult = PORT_Memcmp(firstPtr, secondPtr, firstLen);
  81. }
  82. cleanup:
  83. PKIX_RETURN(BIGINT);
  84. }
  85. /*
  86. * FUNCTION: pkix_pl_BigInt_Destroy
  87. * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
  88. */
  89. static PKIX_Error *
  90. pkix_pl_BigInt_Destroy(
  91. PKIX_PL_Object *object,
  92. void *plContext)
  93. {
  94. PKIX_PL_BigInt *bigInt = NULL;
  95. PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Destroy");
  96. PKIX_NULLCHECK_ONE(object);
  97. PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
  98. PKIX_OBJECTNOTBIGINT);
  99. bigInt = (PKIX_PL_BigInt*)object;
  100. PKIX_FREE(bigInt->dataRep);
  101. bigInt->dataRep = NULL;
  102. bigInt->length = 0;
  103. cleanup:
  104. PKIX_RETURN(BIGINT);
  105. }
  106. /*
  107. * FUNCTION: pkix_pl_BigInt_ToString
  108. * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
  109. */
  110. static PKIX_Error *
  111. pkix_pl_BigInt_ToString(
  112. PKIX_PL_Object *object,
  113. PKIX_PL_String **pString,
  114. void *plContext)
  115. {
  116. PKIX_PL_BigInt *bigInt = NULL;
  117. char *outputText = NULL;
  118. PKIX_UInt32 i, j, lengthChars;
  119. PKIX_ENTER(BIGINT, "pkix_pl_BigInt_ToString");
  120. PKIX_NULLCHECK_TWO(object, pString);
  121. PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
  122. PKIX_OBJECTNOTBIGINT);
  123. bigInt = (PKIX_PL_BigInt*)object;
  124. /* number of chars = 2 * (number of bytes) + null terminator */
  125. lengthChars = (bigInt->length * 2) + 1;
  126. PKIX_CHECK(PKIX_PL_Malloc
  127. (lengthChars, (void **)&outputText, plContext),
  128. PKIX_MALLOCFAILED);
  129. for (i = 0, j = 0; i < bigInt->length; i += 1, j += 2){
  130. outputText[j] = pkix_i2hex
  131. ((char) ((*(bigInt->dataRep+i) & 0xf0) >> 4));
  132. outputText[j+1] = pkix_i2hex
  133. ((char) (*(bigInt->dataRep+i) & 0x0f));
  134. }
  135. outputText[lengthChars-1] = '\0';
  136. PKIX_CHECK(PKIX_PL_String_Create
  137. (PKIX_ESCASCII,
  138. outputText,
  139. 0,
  140. pString,
  141. plContext),
  142. PKIX_STRINGCREATEFAILED);
  143. cleanup:
  144. PKIX_FREE(outputText);
  145. PKIX_RETURN(BIGINT);
  146. }
  147. /*
  148. * FUNCTION: pkix_pl_BigInt_Hashcode
  149. * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
  150. */
  151. static PKIX_Error *
  152. pkix_pl_BigInt_Hashcode(
  153. PKIX_PL_Object *object,
  154. PKIX_UInt32 *pHashcode,
  155. void *plContext)
  156. {
  157. PKIX_PL_BigInt *bigInt = NULL;
  158. PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Hashcode");
  159. PKIX_NULLCHECK_TWO(object, pHashcode);
  160. PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
  161. PKIX_OBJECTNOTBIGINT);
  162. bigInt = (PKIX_PL_BigInt*)object;
  163. PKIX_CHECK(pkix_hash
  164. ((void *)bigInt->dataRep,
  165. bigInt->length,
  166. pHashcode,
  167. plContext),
  168. PKIX_HASHFAILED);
  169. cleanup:
  170. PKIX_RETURN(BIGINT);
  171. }
  172. /*
  173. * FUNCTION: pkix_pl_BigInt_Equals
  174. * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
  175. */
  176. static PKIX_Error *
  177. pkix_pl_BigInt_Equals(
  178. PKIX_PL_Object *first,
  179. PKIX_PL_Object *second,
  180. PKIX_Boolean *pResult,
  181. void *plContext)
  182. {
  183. PKIX_UInt32 secondType;
  184. PKIX_Int32 cmpResult = 0;
  185. PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Equals");
  186. PKIX_NULLCHECK_THREE(first, second, pResult);
  187. PKIX_CHECK(pkix_CheckType(first, PKIX_BIGINT_TYPE, plContext),
  188. PKIX_FIRSTOBJECTNOTBIGINT);
  189. PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
  190. PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
  191. *pResult = PKIX_FALSE;
  192. if (secondType != PKIX_BIGINT_TYPE) goto cleanup;
  193. PKIX_CHECK(pkix_pl_BigInt_Comparator
  194. (first, second, &cmpResult, plContext),
  195. PKIX_BIGINTCOMPARATORFAILED);
  196. *pResult = (cmpResult == 0);
  197. cleanup:
  198. PKIX_RETURN(BIGINT);
  199. }
  200. /*
  201. * FUNCTION: pkix_pl_BigInt_RegisterSelf
  202. * DESCRIPTION:
  203. * Registers PKIX_BIGINT_TYPE and its related functions with systemClasses[]
  204. * THREAD SAFETY:
  205. * Not Thread Safe - for performance and complexity reasons
  206. *
  207. * Since this function is only called by PKIX_PL_Initialize, which should
  208. * only be called once, it is acceptable that this function is not
  209. * thread-safe.
  210. */
  211. PKIX_Error *
  212. pkix_pl_BigInt_RegisterSelf(void *plContext)
  213. {
  214. extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
  215. pkix_ClassTable_Entry entry;
  216. PKIX_ENTER(BIGINT, "pkix_pl_BigInt_RegisterSelf");
  217. entry.description = "BigInt";
  218. entry.objCounter = 0;
  219. entry.typeObjectSize = sizeof(PKIX_PL_BigInt);
  220. entry.destructor = pkix_pl_BigInt_Destroy;
  221. entry.equalsFunction = pkix_pl_BigInt_Equals;
  222. entry.hashcodeFunction = pkix_pl_BigInt_Hashcode;
  223. entry.toStringFunction = pkix_pl_BigInt_ToString;
  224. entry.comparator = pkix_pl_BigInt_Comparator;
  225. entry.duplicateFunction = pkix_duplicateImmutable;
  226. systemClasses[PKIX_BIGINT_TYPE] = entry;
  227. PKIX_RETURN(BIGINT);
  228. }
  229. /*
  230. * FUNCTION: pkix_pl_BigInt_CreateWithBytes
  231. * DESCRIPTION:
  232. *
  233. * Creates a new BigInt of size "length" representing the array of bytes
  234. * pointed to by "bytes" and stores it at "pBigInt". The caller should make
  235. * sure that the first byte is not 0x00 (unless it is the the only byte).
  236. * This function does not do that checking.
  237. *
  238. * Once created, a PKIX_PL_BigInt object is immutable.
  239. *
  240. * PARAMETERS:
  241. * "bytes"
  242. * Address of array of bytes. Must be non-NULL.
  243. * "length"
  244. * Length of the array. Must be non-zero.
  245. * "pBigInt"
  246. * Address where object pointer will be stored. Must be non-NULL.
  247. * "plContext" - Platform-specific context pointer.
  248. * THREAD SAFETY:
  249. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  250. * RETURNS:
  251. * Returns NULL if the function succeeds.
  252. * Returns a Fatal Error if the function fails in an unrecoverable way.
  253. */
  254. PKIX_Error *
  255. pkix_pl_BigInt_CreateWithBytes(
  256. char *bytes,
  257. PKIX_UInt32 length,
  258. PKIX_PL_BigInt **pBigInt,
  259. void *plContext)
  260. {
  261. PKIX_PL_BigInt *bigInt = NULL;
  262. PKIX_ENTER(BIGINT, "pkix_pl_BigInt_CreateWithBytes");
  263. PKIX_NULLCHECK_TWO(pBigInt, bytes);
  264. if (length == 0) {
  265. PKIX_ERROR(PKIX_BIGINTLENGTH0INVALID)
  266. }
  267. PKIX_CHECK(PKIX_PL_Object_Alloc
  268. (PKIX_BIGINT_TYPE,
  269. sizeof (PKIX_PL_BigInt),
  270. (PKIX_PL_Object **)&bigInt,
  271. plContext),
  272. PKIX_COULDNOTCREATEOBJECT);
  273. PKIX_CHECK(PKIX_PL_Malloc
  274. (length, (void **)&(bigInt->dataRep), plContext),
  275. PKIX_MALLOCFAILED);
  276. PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcpy).\n");
  277. (void) PORT_Memcpy(bigInt->dataRep, bytes, length);
  278. bigInt->length = length;
  279. *pBigInt = bigInt;
  280. cleanup:
  281. if (PKIX_ERROR_RECEIVED){
  282. PKIX_DECREF(bigInt);
  283. }
  284. PKIX_RETURN(BIGINT);
  285. }
  286. /* --Public-Functions------------------------------------------------------- */
  287. /*
  288. * FUNCTION: PKIX_PL_BigInt_Create (see comments in pkix_pl_system.h)
  289. */
  290. PKIX_Error *
  291. PKIX_PL_BigInt_Create(
  292. PKIX_PL_String *stringRep,
  293. PKIX_PL_BigInt **pBigInt,
  294. void *plContext)
  295. {
  296. PKIX_PL_BigInt *bigInt = NULL;
  297. char *asciiString = NULL;
  298. PKIX_UInt32 lengthBytes;
  299. PKIX_UInt32 lengthString;
  300. PKIX_UInt32 i;
  301. char currChar;
  302. PKIX_ENTER(BIGINT, "PKIX_PL_BigInt_Create");
  303. PKIX_NULLCHECK_TWO(pBigInt, stringRep);
  304. PKIX_CHECK(PKIX_PL_String_GetEncoded
  305. (stringRep,
  306. PKIX_ESCASCII,
  307. (void **)&asciiString,
  308. &lengthString,
  309. plContext),
  310. PKIX_STRINGGETENCODEDFAILED);
  311. if ((lengthString == 0) || ((lengthString % 2) != 0)){
  312. PKIX_ERROR(PKIX_SOURCESTRINGHASINVALIDLENGTH);
  313. }
  314. if (lengthString != 2){
  315. if ((asciiString[0] == '0') && (asciiString[1] == '0')){
  316. PKIX_ERROR(PKIX_FIRSTDOUBLEHEXMUSTNOTBE00);
  317. }
  318. }
  319. for (i = 0; i < lengthString; i++) {
  320. currChar = asciiString[i];
  321. if (!PKIX_ISXDIGIT(currChar)){
  322. PKIX_ERROR(PKIX_INVALIDCHARACTERINBIGINT);
  323. }
  324. }
  325. PKIX_CHECK(PKIX_PL_Object_Alloc
  326. (PKIX_BIGINT_TYPE,
  327. sizeof (PKIX_PL_BigInt),
  328. (PKIX_PL_Object **)&bigInt,
  329. plContext),
  330. PKIX_COULDNOTCREATEOBJECT);
  331. /* number of bytes = 0.5 * (number of chars) */
  332. lengthBytes = lengthString/2;
  333. PKIX_CHECK(PKIX_PL_Malloc
  334. (lengthBytes, (void **)&(bigInt->dataRep), plContext),
  335. PKIX_MALLOCFAILED);
  336. for (i = 0; i < lengthString; i += 2){
  337. (bigInt->dataRep)[i/2] =
  338. (pkix_hex2i(asciiString[i])<<4) |
  339. pkix_hex2i(asciiString[i+1]);
  340. }
  341. bigInt->length = lengthBytes;
  342. *pBigInt = bigInt;
  343. cleanup:
  344. PKIX_FREE(asciiString);
  345. if (PKIX_ERROR_RECEIVED){
  346. PKIX_DECREF(bigInt);
  347. }
  348. PKIX_RETURN(BIGINT);
  349. }