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
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.
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 ***** */
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)
53 pkix_pl_BigInt_Comparator(
54 PKIX_PL_Object
*firstObject
,
55 PKIX_PL_Object
*secondObject
,
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
;
77 firstPtr
= firstBigInt
->dataRep
;
78 secondPtr
= secondBigInt
->dataRep
;
79 firstLen
= firstBigInt
->length
;
80 secondLen
= secondBigInt
->length
;
82 if (firstLen
< secondLen
) {
84 } else if (firstLen
> secondLen
) {
86 } else if (firstLen
== secondLen
) {
87 PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcmp).\n");
88 *pResult
= PORT_Memcmp(firstPtr
, secondPtr
, firstLen
);
97 * FUNCTION: pkix_pl_BigInt_Destroy
98 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
101 pkix_pl_BigInt_Destroy(
102 PKIX_PL_Object
*object
,
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
;
126 * FUNCTION: pkix_pl_BigInt_ToString
127 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
130 pkix_pl_BigInt_ToString(
131 PKIX_PL_Object
*object
,
132 PKIX_PL_String
**pString
,
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
),
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
169 PKIX_STRINGCREATEFAILED
);
173 PKIX_FREE(outputText
);
180 * FUNCTION: pkix_pl_BigInt_Hashcode
181 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
184 pkix_pl_BigInt_Hashcode(
185 PKIX_PL_Object
*object
,
186 PKIX_UInt32
*pHashcode
,
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
;
200 ((void *)bigInt
->dataRep
,
212 * FUNCTION: pkix_pl_BigInt_Equals
213 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
216 pkix_pl_BigInt_Equals(
217 PKIX_PL_Object
*first
,
218 PKIX_PL_Object
*second
,
219 PKIX_Boolean
*pResult
,
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);
250 * FUNCTION: pkix_pl_BigInt_RegisterSelf
252 * Registers PKIX_BIGINT_TYPE and its related functions with systemClasses[]
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
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
;
285 * FUNCTION: pkix_pl_BigInt_CreateWithBytes
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.
297 * Address of array of bytes. Must be non-NULL.
299 * Length of the array. Must be non-zero.
301 * Address where object pointer will be stored. Must be non-NULL.
302 * "plContext" - Platform-specific context pointer.
304 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
306 * Returns NULL if the function succeeds.
307 * Returns a Fatal Error if the function fails in an unrecoverable way.
310 pkix_pl_BigInt_CreateWithBytes(
313 PKIX_PL_BigInt
**pBigInt
,
316 PKIX_PL_BigInt
*bigInt
= NULL
;
318 PKIX_ENTER(BIGINT
, "pkix_pl_BigInt_CreateWithBytes");
319 PKIX_NULLCHECK_TWO(pBigInt
, bytes
);
322 PKIX_ERROR(PKIX_BIGINTLENGTH0INVALID
)
325 PKIX_CHECK(PKIX_PL_Object_Alloc
327 sizeof (PKIX_PL_BigInt
),
328 (PKIX_PL_Object
**)&bigInt
,
330 PKIX_COULDNOTCREATEOBJECT
);
332 PKIX_CHECK(PKIX_PL_Malloc
333 (length
, (void **)&(bigInt
->dataRep
), plContext
),
336 PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcpy).\n");
337 (void) PORT_Memcpy(bigInt
->dataRep
, bytes
, length
);
339 bigInt
->length
= length
;
345 if (PKIX_ERROR_RECEIVED
){
352 /* --Public-Functions------------------------------------------------------- */
355 * FUNCTION: PKIX_PL_BigInt_Create (see comments in pkix_pl_system.h)
358 PKIX_PL_BigInt_Create(
359 PKIX_PL_String
*stringRep
,
360 PKIX_PL_BigInt
**pBigInt
,
363 PKIX_PL_BigInt
*bigInt
= NULL
;
364 char *asciiString
= NULL
;
365 PKIX_UInt32 lengthBytes
;
366 PKIX_UInt32 lengthString
;
370 PKIX_ENTER(BIGINT
, "PKIX_PL_BigInt_Create");
371 PKIX_NULLCHECK_TWO(pBigInt
, stringRep
);
373 PKIX_CHECK(PKIX_PL_String_GetEncoded
376 (void **)&asciiString
,
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
400 sizeof (PKIX_PL_BigInt
),
401 (PKIX_PL_Object
**)&bigInt
,
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
),
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
;
424 PKIX_FREE(asciiString
);
426 if (PKIX_ERROR_RECEIVED
){