nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / system / pkix_pl_bigint.c
blob7a5bdee375fb44a4e25e2cca773d4e5b19318b32
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
14 * The Original Code is the PKIX-C library.
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.
21 * Contributor(s):
22 * Sun Microsystems, Inc.
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.
36 * ***** END LICENSE BLOCK ***** */
38 * pkix_pl_bigint.c
40 * BigInt Object Functions
44 #include "pkix_pl_bigint.h"
46 /* --Private-Big-Int-Functions------------------------------------ */
49 * FUNCTION: pkix_pl_BigInt_Comparator
50 * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
52 static PKIX_Error *
53 pkix_pl_BigInt_Comparator(
54 PKIX_PL_Object *firstObject,
55 PKIX_PL_Object *secondObject,
56 PKIX_Int32 *pResult,
57 void *plContext)
59 PKIX_PL_BigInt *firstBigInt = NULL;
60 PKIX_PL_BigInt *secondBigInt = NULL;
61 char *firstPtr = NULL;
62 char *secondPtr = NULL;
63 PKIX_UInt32 firstLen, secondLen;
65 PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Comparator");
66 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
68 PKIX_CHECK(pkix_CheckTypes
69 (firstObject, secondObject, PKIX_BIGINT_TYPE, plContext),
70 PKIX_ARGUMENTSNOTBIGINTS);
72 /* It's safe to cast */
73 firstBigInt = (PKIX_PL_BigInt*)firstObject;
74 secondBigInt = (PKIX_PL_BigInt*)secondObject;
76 *pResult = 0;
77 firstPtr = firstBigInt->dataRep;
78 secondPtr = secondBigInt->dataRep;
79 firstLen = firstBigInt->length;
80 secondLen = secondBigInt->length;
82 if (firstLen < secondLen) {
83 *pResult = -1;
84 } else if (firstLen > secondLen) {
85 *pResult = 1;
86 } else if (firstLen == secondLen) {
87 PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcmp).\n");
88 *pResult = PORT_Memcmp(firstPtr, secondPtr, firstLen);
91 cleanup:
93 PKIX_RETURN(BIGINT);
97 * FUNCTION: pkix_pl_BigInt_Destroy
98 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
100 static PKIX_Error *
101 pkix_pl_BigInt_Destroy(
102 PKIX_PL_Object *object,
103 void *plContext)
105 PKIX_PL_BigInt *bigInt = NULL;
107 PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Destroy");
108 PKIX_NULLCHECK_ONE(object);
110 PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
111 PKIX_OBJECTNOTBIGINT);
113 bigInt = (PKIX_PL_BigInt*)object;
115 PKIX_FREE(bigInt->dataRep);
116 bigInt->dataRep = NULL;
117 bigInt->length = 0;
119 cleanup:
121 PKIX_RETURN(BIGINT);
126 * FUNCTION: pkix_pl_BigInt_ToString
127 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
129 static PKIX_Error *
130 pkix_pl_BigInt_ToString(
131 PKIX_PL_Object *object,
132 PKIX_PL_String **pString,
133 void *plContext)
135 PKIX_PL_BigInt *bigInt = NULL;
136 char *outputText = NULL;
137 PKIX_UInt32 i, j, lengthChars;
139 PKIX_ENTER(BIGINT, "pkix_pl_BigInt_ToString");
140 PKIX_NULLCHECK_TWO(object, pString);
142 PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
143 PKIX_OBJECTNOTBIGINT);
145 bigInt = (PKIX_PL_BigInt*)object;
147 /* number of chars = 2 * (number of bytes) + null terminator */
148 lengthChars = (bigInt->length * 2) + 1;
150 PKIX_CHECK(PKIX_PL_Malloc
151 (lengthChars, (void **)&outputText, plContext),
152 PKIX_MALLOCFAILED);
154 for (i = 0, j = 0; i < bigInt->length; i += 1, j += 2){
155 outputText[j] = pkix_i2hex
156 ((char) ((*(bigInt->dataRep+i) & 0xf0) >> 4));
157 outputText[j+1] = pkix_i2hex
158 ((char) (*(bigInt->dataRep+i) & 0x0f));
161 outputText[lengthChars-1] = '\0';
163 PKIX_CHECK(PKIX_PL_String_Create
164 (PKIX_ESCASCII,
165 outputText,
167 pString,
168 plContext),
169 PKIX_STRINGCREATEFAILED);
171 cleanup:
173 PKIX_FREE(outputText);
175 PKIX_RETURN(BIGINT);
180 * FUNCTION: pkix_pl_BigInt_Hashcode
181 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
183 static PKIX_Error *
184 pkix_pl_BigInt_Hashcode(
185 PKIX_PL_Object *object,
186 PKIX_UInt32 *pHashcode,
187 void *plContext)
189 PKIX_PL_BigInt *bigInt = NULL;
191 PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Hashcode");
192 PKIX_NULLCHECK_TWO(object, pHashcode);
194 PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
195 PKIX_OBJECTNOTBIGINT);
197 bigInt = (PKIX_PL_BigInt*)object;
199 PKIX_CHECK(pkix_hash
200 ((void *)bigInt->dataRep,
201 bigInt->length,
202 pHashcode,
203 plContext),
204 PKIX_HASHFAILED);
206 cleanup:
208 PKIX_RETURN(BIGINT);
212 * FUNCTION: pkix_pl_BigInt_Equals
213 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
215 static PKIX_Error *
216 pkix_pl_BigInt_Equals(
217 PKIX_PL_Object *first,
218 PKIX_PL_Object *second,
219 PKIX_Boolean *pResult,
220 void *plContext)
222 PKIX_UInt32 secondType;
223 PKIX_Int32 cmpResult = 0;
225 PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Equals");
226 PKIX_NULLCHECK_THREE(first, second, pResult);
228 PKIX_CHECK(pkix_CheckType(first, PKIX_BIGINT_TYPE, plContext),
229 PKIX_FIRSTOBJECTNOTBIGINT);
231 PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
232 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
234 *pResult = PKIX_FALSE;
236 if (secondType != PKIX_BIGINT_TYPE) goto cleanup;
238 PKIX_CHECK(pkix_pl_BigInt_Comparator
239 (first, second, &cmpResult, plContext),
240 PKIX_BIGINTCOMPARATORFAILED);
242 *pResult = (cmpResult == 0);
244 cleanup:
246 PKIX_RETURN(BIGINT);
250 * FUNCTION: pkix_pl_BigInt_RegisterSelf
251 * DESCRIPTION:
252 * Registers PKIX_BIGINT_TYPE and its related functions with systemClasses[]
253 * THREAD SAFETY:
254 * Not Thread Safe - for performance and complexity reasons
256 * Since this function is only called by PKIX_PL_Initialize, which should
257 * only be called once, it is acceptable that this function is not
258 * thread-safe.
260 PKIX_Error *
261 pkix_pl_BigInt_RegisterSelf(void *plContext)
264 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
265 pkix_ClassTable_Entry entry;
267 PKIX_ENTER(BIGINT, "pkix_pl_BigInt_RegisterSelf");
269 entry.description = "BigInt";
270 entry.objCounter = 0;
271 entry.typeObjectSize = sizeof(PKIX_PL_BigInt);
272 entry.destructor = pkix_pl_BigInt_Destroy;
273 entry.equalsFunction = pkix_pl_BigInt_Equals;
274 entry.hashcodeFunction = pkix_pl_BigInt_Hashcode;
275 entry.toStringFunction = pkix_pl_BigInt_ToString;
276 entry.comparator = pkix_pl_BigInt_Comparator;
277 entry.duplicateFunction = pkix_duplicateImmutable;
279 systemClasses[PKIX_BIGINT_TYPE] = entry;
281 PKIX_RETURN(BIGINT);
285 * FUNCTION: pkix_pl_BigInt_CreateWithBytes
286 * DESCRIPTION:
288 * Creates a new BigInt of size "length" representing the array of bytes
289 * pointed to by "bytes" and stores it at "pBigInt". The caller should make
290 * sure that the first byte is not 0x00 (unless it is the the only byte).
291 * This function does not do that checking.
293 * Once created, a PKIX_PL_BigInt object is immutable.
295 * PARAMETERS:
296 * "bytes"
297 * Address of array of bytes. Must be non-NULL.
298 * "length"
299 * Length of the array. Must be non-zero.
300 * "pBigInt"
301 * Address where object pointer will be stored. Must be non-NULL.
302 * "plContext" - Platform-specific context pointer.
303 * THREAD SAFETY:
304 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
305 * RETURNS:
306 * Returns NULL if the function succeeds.
307 * Returns a Fatal Error if the function fails in an unrecoverable way.
309 PKIX_Error *
310 pkix_pl_BigInt_CreateWithBytes(
311 char *bytes,
312 PKIX_UInt32 length,
313 PKIX_PL_BigInt **pBigInt,
314 void *plContext)
316 PKIX_PL_BigInt *bigInt = NULL;
318 PKIX_ENTER(BIGINT, "pkix_pl_BigInt_CreateWithBytes");
319 PKIX_NULLCHECK_TWO(pBigInt, bytes);
321 if (length == 0) {
322 PKIX_ERROR(PKIX_BIGINTLENGTH0INVALID)
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);
332 PKIX_CHECK(PKIX_PL_Malloc
333 (length, (void **)&(bigInt->dataRep), plContext),
334 PKIX_MALLOCFAILED);
336 PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcpy).\n");
337 (void) PORT_Memcpy(bigInt->dataRep, bytes, length);
339 bigInt->length = length;
341 *pBigInt = bigInt;
343 cleanup:
345 if (PKIX_ERROR_RECEIVED){
346 PKIX_DECREF(bigInt);
349 PKIX_RETURN(BIGINT);
352 /* --Public-Functions------------------------------------------------------- */
355 * FUNCTION: PKIX_PL_BigInt_Create (see comments in pkix_pl_system.h)
357 PKIX_Error *
358 PKIX_PL_BigInt_Create(
359 PKIX_PL_String *stringRep,
360 PKIX_PL_BigInt **pBigInt,
361 void *plContext)
363 PKIX_PL_BigInt *bigInt = NULL;
364 char *asciiString = NULL;
365 PKIX_UInt32 lengthBytes;
366 PKIX_UInt32 lengthString;
367 PKIX_UInt32 i;
368 char currChar;
370 PKIX_ENTER(BIGINT, "PKIX_PL_BigInt_Create");
371 PKIX_NULLCHECK_TWO(pBigInt, stringRep);
373 PKIX_CHECK(PKIX_PL_String_GetEncoded
374 (stringRep,
375 PKIX_ESCASCII,
376 (void **)&asciiString,
377 &lengthString,
378 plContext),
379 PKIX_STRINGGETENCODEDFAILED);
381 if ((lengthString == 0) || ((lengthString % 2) != 0)){
382 PKIX_ERROR(PKIX_SOURCESTRINGHASINVALIDLENGTH);
385 if (lengthString != 2){
386 if ((asciiString[0] == '0') && (asciiString[1] == '0')){
387 PKIX_ERROR(PKIX_FIRSTDOUBLEHEXMUSTNOTBE00);
391 for (i = 0; i < lengthString; i++) {
392 currChar = asciiString[i];
393 if (!PKIX_ISXDIGIT(currChar)){
394 PKIX_ERROR(PKIX_INVALIDCHARACTERINBIGINT);
398 PKIX_CHECK(PKIX_PL_Object_Alloc
399 (PKIX_BIGINT_TYPE,
400 sizeof (PKIX_PL_BigInt),
401 (PKIX_PL_Object **)&bigInt,
402 plContext),
403 PKIX_COULDNOTCREATEOBJECT);
405 /* number of bytes = 0.5 * (number of chars) */
406 lengthBytes = lengthString/2;
408 PKIX_CHECK(PKIX_PL_Malloc
409 (lengthBytes, (void **)&(bigInt->dataRep), plContext),
410 PKIX_MALLOCFAILED);
412 for (i = 0; i < lengthString; i += 2){
413 (bigInt->dataRep)[i/2] =
414 (pkix_hex2i(asciiString[i])<<4) |
415 pkix_hex2i(asciiString[i+1]);
418 bigInt->length = lengthBytes;
420 *pBigInt = bigInt;
422 cleanup:
424 PKIX_FREE(asciiString);
426 if (PKIX_ERROR_RECEIVED){
427 PKIX_DECREF(bigInt);
430 PKIX_RETURN(BIGINT);