PageRenderTime 44ms CodeModel.GetById 17ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 44#include "pkix_pl_bigint.h"
 45
 46/* --Private-Big-Int-Functions------------------------------------ */
 47
 48/*
 49 * FUNCTION: pkix_pl_BigInt_Comparator
 50 * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
 51 */
 52static PKIX_Error *
 53pkix_pl_BigInt_Comparator(
 54        PKIX_PL_Object *firstObject,
 55        PKIX_PL_Object *secondObject,
 56        PKIX_Int32 *pResult,
 57        void *plContext)
 58{
 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;
 64
 65        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Comparator");
 66        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
 67
 68        PKIX_CHECK(pkix_CheckTypes
 69                    (firstObject, secondObject, PKIX_BIGINT_TYPE, plContext),
 70                    PKIX_ARGUMENTSNOTBIGINTS);
 71
 72        /* It's safe to cast */
 73        firstBigInt = (PKIX_PL_BigInt*)firstObject;
 74        secondBigInt = (PKIX_PL_BigInt*)secondObject;
 75
 76        *pResult = 0;
 77        firstPtr = firstBigInt->dataRep;
 78        secondPtr = secondBigInt->dataRep;
 79        firstLen = firstBigInt->length;
 80        secondLen = secondBigInt->length;
 81
 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);
 89        }
 90
 91cleanup:
 92
 93        PKIX_RETURN(BIGINT);
 94}
 95
 96/*
 97 * FUNCTION: pkix_pl_BigInt_Destroy
 98 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
 99 */
100static PKIX_Error *
101pkix_pl_BigInt_Destroy(
102        PKIX_PL_Object *object,
103        void *plContext)
104{
105        PKIX_PL_BigInt *bigInt = NULL;
106
107        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Destroy");
108        PKIX_NULLCHECK_ONE(object);
109
110        PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
111                    PKIX_OBJECTNOTBIGINT);
112
113        bigInt = (PKIX_PL_BigInt*)object;
114
115        PKIX_FREE(bigInt->dataRep);
116        bigInt->dataRep = NULL;
117        bigInt->length = 0;
118
119cleanup:
120
121        PKIX_RETURN(BIGINT);
122}
123
124
125/*
126 * FUNCTION: pkix_pl_BigInt_ToString
127 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
128 */
129static PKIX_Error *
130pkix_pl_BigInt_ToString(
131        PKIX_PL_Object *object,
132        PKIX_PL_String **pString,
133        void *plContext)
134{
135        PKIX_PL_BigInt *bigInt = NULL;
136        char *outputText = NULL;
137        PKIX_UInt32 i, j, lengthChars;
138
139        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_ToString");
140        PKIX_NULLCHECK_TWO(object, pString);
141
142        PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
143                    PKIX_OBJECTNOTBIGINT);
144
145        bigInt = (PKIX_PL_BigInt*)object;
146
147        /* number of chars = 2 * (number of bytes) + null terminator */
148        lengthChars = (bigInt->length * 2) + 1;
149
150        PKIX_CHECK(PKIX_PL_Malloc
151                    (lengthChars, (void **)&outputText, plContext),
152                    PKIX_MALLOCFAILED);
153
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));
159        }
160
161        outputText[lengthChars-1] = '\0';
162
163        PKIX_CHECK(PKIX_PL_String_Create
164                    (PKIX_ESCASCII,
165                    outputText,
166                    0,
167                    pString,
168                    plContext),
169                    PKIX_STRINGCREATEFAILED);
170
171cleanup:
172
173        PKIX_FREE(outputText);
174
175        PKIX_RETURN(BIGINT);
176}
177
178
179/*
180 * FUNCTION: pkix_pl_BigInt_Hashcode
181 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
182 */
183static PKIX_Error *
184pkix_pl_BigInt_Hashcode(
185        PKIX_PL_Object *object,
186        PKIX_UInt32 *pHashcode,
187        void *plContext)
188{
189        PKIX_PL_BigInt *bigInt = NULL;
190
191        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Hashcode");
192        PKIX_NULLCHECK_TWO(object, pHashcode);
193
194        PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
195                    PKIX_OBJECTNOTBIGINT);
196
197        bigInt = (PKIX_PL_BigInt*)object;
198
199        PKIX_CHECK(pkix_hash
200                    ((void *)bigInt->dataRep,
201                    bigInt->length,
202                    pHashcode,
203                    plContext),
204                    PKIX_HASHFAILED);
205
206cleanup:
207
208        PKIX_RETURN(BIGINT);
209}
210
211/*
212 * FUNCTION: pkix_pl_BigInt_Equals
213 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
214 */
215static PKIX_Error *
216pkix_pl_BigInt_Equals(
217        PKIX_PL_Object *first,
218        PKIX_PL_Object *second,
219        PKIX_Boolean *pResult,
220        void *plContext)
221{
222        PKIX_UInt32 secondType;
223        PKIX_Int32 cmpResult = 0;
224
225        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Equals");
226        PKIX_NULLCHECK_THREE(first, second, pResult);
227
228        PKIX_CHECK(pkix_CheckType(first, PKIX_BIGINT_TYPE, plContext),
229                PKIX_FIRSTOBJECTNOTBIGINT);
230
231        PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
232                PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
233
234        *pResult = PKIX_FALSE;
235
236        if (secondType != PKIX_BIGINT_TYPE) goto cleanup;
237
238        PKIX_CHECK(pkix_pl_BigInt_Comparator
239                (first, second, &cmpResult, plContext),
240                PKIX_BIGINTCOMPARATORFAILED);
241
242        *pResult = (cmpResult == 0);
243
244cleanup:
245
246        PKIX_RETURN(BIGINT);
247}
248
249/*
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
255 *
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.
259 */
260PKIX_Error *
261pkix_pl_BigInt_RegisterSelf(void *plContext)
262{
263
264        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
265        pkix_ClassTable_Entry entry;
266
267        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_RegisterSelf");
268
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;
278
279        systemClasses[PKIX_BIGINT_TYPE] = entry;
280
281        PKIX_RETURN(BIGINT);
282}
283
284/*
285 * FUNCTION: pkix_pl_BigInt_CreateWithBytes
286 * DESCRIPTION:
287 *
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.
292 *
293 *  Once created, a PKIX_PL_BigInt object is immutable.
294 *
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.
308 */
309PKIX_Error *
310pkix_pl_BigInt_CreateWithBytes(
311        char *bytes,
312        PKIX_UInt32 length,
313        PKIX_PL_BigInt **pBigInt,
314        void *plContext)
315{
316        PKIX_PL_BigInt *bigInt = NULL;
317
318        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_CreateWithBytes");
319        PKIX_NULLCHECK_TWO(pBigInt, bytes);
320
321        if (length == 0) {
322                PKIX_ERROR(PKIX_BIGINTLENGTH0INVALID)
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
332        PKIX_CHECK(PKIX_PL_Malloc
333                    (length, (void **)&(bigInt->dataRep), plContext),
334                    PKIX_MALLOCFAILED);
335
336        PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcpy).\n");
337        (void) PORT_Memcpy(bigInt->dataRep, bytes, length);
338
339        bigInt->length = length;
340
341        *pBigInt = bigInt;
342
343cleanup:
344
345        if (PKIX_ERROR_RECEIVED){
346                PKIX_DECREF(bigInt);
347        }
348
349        PKIX_RETURN(BIGINT);
350}
351
352/* --Public-Functions------------------------------------------------------- */
353
354/*
355 * FUNCTION: PKIX_PL_BigInt_Create (see comments in pkix_pl_system.h)
356 */
357PKIX_Error *
358PKIX_PL_BigInt_Create(
359        PKIX_PL_String *stringRep,
360        PKIX_PL_BigInt **pBigInt,
361        void *plContext)
362{
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;
369
370        PKIX_ENTER(BIGINT, "PKIX_PL_BigInt_Create");
371        PKIX_NULLCHECK_TWO(pBigInt, stringRep);
372
373        PKIX_CHECK(PKIX_PL_String_GetEncoded
374                (stringRep,
375                PKIX_ESCASCII,
376                (void **)&asciiString,
377                &lengthString,
378                plContext),
379                PKIX_STRINGGETENCODEDFAILED);
380
381        if ((lengthString == 0) || ((lengthString % 2) != 0)){
382                PKIX_ERROR(PKIX_SOURCESTRINGHASINVALIDLENGTH);
383        }
384
385        if (lengthString != 2){
386                if ((asciiString[0] == '0') && (asciiString[1] == '0')){
387                        PKIX_ERROR(PKIX_FIRSTDOUBLEHEXMUSTNOTBE00);
388                }
389        }
390
391        for (i = 0; i < lengthString; i++) {
392                currChar = asciiString[i];
393                if (!PKIX_ISXDIGIT(currChar)){
394                        PKIX_ERROR(PKIX_INVALIDCHARACTERINBIGINT);
395                }
396        }
397
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);
404
405        /* number of bytes = 0.5 * (number of chars) */
406        lengthBytes = lengthString/2;
407
408        PKIX_CHECK(PKIX_PL_Malloc
409                    (lengthBytes, (void **)&(bigInt->dataRep), plContext),
410                    PKIX_MALLOCFAILED);
411
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]);
416        }
417
418        bigInt->length = lengthBytes;
419
420        *pBigInt = bigInt;
421
422cleanup:
423
424        PKIX_FREE(asciiString);
425
426        if (PKIX_ERROR_RECEIVED){
427                PKIX_DECREF(bigInt);
428        }
429
430        PKIX_RETURN(BIGINT);
431}