X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/OSX/libsecurity_cryptkit/lib/ckutilities.c diff --git a/OSX/libsecurity_cryptkit/lib/ckutilities.c b/OSX/libsecurity_cryptkit/lib/ckutilities.c new file mode 100644 index 00000000..bbbe252b --- /dev/null +++ b/OSX/libsecurity_cryptkit/lib/ckutilities.c @@ -0,0 +1,416 @@ +/* Copyright (c) 1998,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * ckutilities.c - general C routines + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 08 Apr 98 at Apple + * Mods for variable size giantDigit. + * Rewrote serializeGiant(), deserializeGiant() to conform to IEEE P1363. + * 23 Mar 98 at Apple + * Added FR_WrongSignatureType, FR_BadKeyBlob to frtnStrings. + * Added initCryptKit(). + * 19 Jan 98 at Apple + * Added cStringToUc() + * 09 Jan 98 at Apple + * Added non-FEE_DEBUG version of printGiantHex() + * 27 Jan 97 at NeXT + * Addd serializeGiant(), deserializeGiant; Deleted data_to_giant() + * 12 Dec 96 at NeXT + * Added byteRepTo{int,key,giant}(). + * 2 Aug 96 at NeXT + * Broke out from Blaine Garst's original NSCryptors.m + */ + +#include "ckutilities.h" +#include "falloc.h" +#include "feeTypes.h" +#include "feeDebug.h" +#include "feeFunctions.h" +#include "byteRep.h" +#include "platform.h" +#include "curveParams.h" +#include +#ifdef NeXT +#include +#include +#include +#include +#endif // NeXT + +/* + * feeReturn strings. + */ +typedef struct { + feeReturn frtn; + const char *frtnString; +} frtnItem; + +static const frtnItem frtnStrings[] = { +#ifndef NDEBUG + { FR_Success, "Success" }, + { FR_BadPubKey, "Bad Public Key" }, + { FR_BadPubKeyString, "Bad Public Key String" }, + { FR_IncompatibleKey, "Incompatible key format" }, + { FR_IllegalDepth, "Illegal Depth" }, + { FR_BadUsageName, "Bad Usage Name" }, + { FR_BadSignatureFormat, "Bad Signature Format" }, + { FR_InvalidSignature, "Invalid Signature" }, + { FR_IllegalArg, "Illegal Argument" }, + { FR_BadCipherText, "Bad Ciphertext Format" }, + { FR_Unimplemented, "Unimplemented Function" }, + { FR_BadCipherFile, "Bad CipherFile Format" }, + { FR_BadEnc64, "Bad enc64 Format" }, + { FR_WrongSignatureType, "Wrong Signature Type" }, + { FR_BadKeyBlob, "Bad Key Blob" }, + { FR_IllegalCurve, "Bad curve type" }, + { FR_Internal, "Internal Library Error" }, + { FR_Memory, "Out of Memory" }, + { FR_ShortPrivData, "Insufficient Seed Data" }, +#endif /* NDEBUG */ + { (feeReturn) 0, NULL }, +}; + +/* + * One-time only init of CryptKit library. + */ +void initCryptKit(void) +{ + #if GIANTS_VIA_STACK + curveParamsInitGiants(); + #endif +} + +/* + * Shutdown. + */ +void terminateCryptKit(void) +{ + #if GIANTS_VIA_STACK + freeGiantStacks(); + #endif +} + +/* + * Create a giant, initialized with specified char[] data. + */ +giant giant_with_data(const unsigned char *d, int len) { + int numDigits = BYTES_TO_GIANT_DIGITS(len); + giant result; + + result = newGiant(numDigits); + deserializeGiant(d, result, len); + return result; +} + +/* + * Obtain a malloc'd memory chunk init'd with specified giant's data. + * Resulting bytes are portable. Size of malloc'd memory is always zero + * mod GIANT_BYTES_PER_DIGIT. + * + * Calling this function for a giant obtained by giant_with_data() yields + * the original data, with extra byte(s) of leading zeros if the original + * was not zero mod GIANT_BYTES_PER_DIGIT. + */ +unsigned char *mem_from_giant(giant g, + unsigned *memLen) /* RETURNED size of malloc'd region */ +{ + unsigned char *cp; + unsigned numDigits = (g->sign < 0) ? -g->sign : g->sign; + + *memLen = numDigits * GIANT_BYTES_PER_DIGIT; + cp = (unsigned char*) fmalloc(*memLen); + serializeGiant(g, cp, *memLen); + return cp; +} + +extern const char *feeReturnString(feeReturn frtn) +{ + const frtnItem *fi = frtnStrings; + + while(fi->frtnString) { + if(fi->frtn == frtn) { + return fi->frtnString; + } + fi++; + } + return "Unknown Status"; +} + +#if FEE_DEBUG +void printGiant(const giant x) +{ + int i; + + printf("sign=%d cap=%d n[]=", x->sign, x->capacity); + for(i=0; isign); i++) { + printf("%u:", x->n[i]); + } + printf("\n"); +} + +void printGiantHex(const giant x) +{ + int i; + + printf("sign=%d cap=%d n[]=", x->sign, x->capacity); + for(i=0; isign); i++) { + printf("%x:", x->n[i]); + } + printf("\n"); +} + +/* + * Print in the form + * sign=8 cap=16 n[]=29787 + 3452 * w^1 + 55260 * w^2 + ... + */ +void printGiantExp(const giant x) +{ + int i; + int size = abs(x->sign); + + printf("sign=%d cap=%d n[]=", x->sign, x->capacity); + for(i=0; in[i]); + if(i > 0) { + printf("* w^%d ", i); + } + if(i<(size-1)) { + printf("+ "); + } + } + printf("\n"); +} + +void printKey(const key k) +{ + printf(" twist %d\n", k->twist); + printf(" x: "); + printGiant(k->x); +} + +void printCurveParams(const curveParams *p) +{ + const char *pt; + const char *ct; + + switch(p->primeType) { + case FPT_Mersenne: + pt = "FPT_Mersenne"; + break; + case FPT_FEE: + pt = "FPT_FEE"; + break; + case FPT_General: + pt = "FPT_General"; + break; + default: + pt = "UNKNOWN!"; + break; + } + switch(p->curveType) { + case FCT_Montgomery: + ct = "FCT_Montgomery"; + break; + case FCT_Weierstrass: + ct = "FCT_Weierstrass"; + break; + case FCT_General: + ct = "FCT_General"; + break; + default: + ct = "UNKNOWN!"; + break; + } + printf(" q %d k %d primeType %s curveType %s\n", + p->q, p->k, pt, ct); + printf(" minBytes %d maxDigits %d\n", p->minBytes, p->maxDigits); + printf(" a : "); + printGiant(p->a); + printf(" b : "); + printGiant(p->b); + printf(" c : "); + printGiant(p->c); + printf(" basePrime : "); + printGiant(p->basePrime); + printf(" x1Plus : "); + printGiant(p->x1Plus); + printf(" x1Minus : "); + printGiant(p->x1Minus); + printf(" cOrderPlus : "); + printGiant(p->cOrderPlus); + printf(" cOrderMinus : "); + printGiant(p->cOrderMinus); + printf(" x1OrderPlus : "); + printGiant(p->x1OrderPlus); + printf(" x1OrderMinus: "); + printGiant(p->x1OrderMinus); +} +#else +void printGiant(const giant x) {} +void printGiantHex(const giant x) {} +void printGiantExp(const giant x) {} +void printKey(const key k) {} +void printCurveParams(const curveParams *p) {} + +#endif /* FEE_DEBUG */ + +#if defined(NeXT) && !defined(WIN32) + +void getpassword(const char *prompt, char *pbuf) +{ + struct sgttyb ttyb; + int flags; + register char *p; + register int c; + FILE *fi; + void (*sig)(int); + + if ((fi = fdopen(open("/dev/tty", 2, 0), "r")) == NULL) + fi = stdin; + else + setbuf(fi, (char *)NULL); + sig = signal(SIGINT, SIG_IGN); + ioctl(fileno(fi), TIOCGETP, &ttyb); + flags = ttyb.sg_flags; + ttyb.sg_flags &= ~ECHO; + ioctl(fileno(fi), TIOCSETP, &ttyb); + fprintf(stderr, "%s", prompt); fflush(stderr); + for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) { + if (p < &pbuf[PHRASELEN-1]) + *p++ = c; + } + *p = '\0'; + fprintf(stderr, "\n"); fflush(stderr); + ttyb.sg_flags = flags; + ioctl(fileno(fi), TIOCSETP, &ttyb); + (void)signal(SIGINT, sig); + if (fi != stdin) + fclose(fi); +} +#endif // NeXT + +/* + * serialize, deserialize giants's n[] to/from byte stream. + * First byte of byte stream is the MS byte of the resulting giant, + * regardless of the size of giantDigit. + * + * No assumption is made about the alignment of cp. + * + * As of 7 Apr 1998, these routines are in compliance with IEEE P1363, + * section 5.5.1, for the representation of a large integer as a byte + * stream. + */ +void serializeGiant(giant g, + unsigned char *cp, + unsigned numBytes) +{ + unsigned digitDex; + unsigned numDigits = BYTES_TO_GIANT_DIGITS(numBytes); + giantDigit digit; + unsigned char *ptr; + unsigned digitByte; + int size = abs(g->sign); + + if(numBytes == 0) { + return; + } + if(numBytes > (g->capacity * GIANT_BYTES_PER_DIGIT)) { + CKRaise("serializeGiant: CAPACITY EXCEEDED!\n"); + } + + /* + * note we might be asked to write more than the valid number + * if bytes in the giant in the case if truncated sign due to + * zero M.S. digit(s).... + */ + + /* + * zero out unused digits so we can infer sign during deserialize + */ + for(digitDex=size; digitDexn[digitDex] = 0; + } + + /* + * Emit bytes starting from l.s. byte. L.s. byte of the outgoing + * data stream is *last*. L.s. digit of giant's digits is *first*. + */ + digitDex = 0; + ptr = &cp[numBytes - 1]; + do { + /* one loop per giant digit */ + digit = g->n[digitDex++]; + for(digitByte=0; digitByte>= 8; + } + } while(numBytes != 0); + +} + +/* + * Resulting sign here is always positive; leading zeroes are reflected + * in an altered g->sign. + */ +void deserializeGiant(const unsigned char *cp, + giant g, + unsigned numBytes) +{ + unsigned numDigits; + giantDigit digit; + int digitDex; + unsigned digitByte; + const unsigned char *ptr; + + if(numBytes == 0) { + g->sign = 0; + return; + } + numDigits = (numBytes + GIANT_BYTES_PER_DIGIT - 1) / + GIANT_BYTES_PER_DIGIT; + if(numBytes > (g->capacity * GIANT_BYTES_PER_DIGIT)) { + CKRaise("deserializeGiant: CAPACITY EXCEEDED!\n"); + } + + /* + * Start at l.s. byte. That's the end of the cp[] array and + * the beginning of the giantDigit array. + */ + digitDex = 0; + ptr = &cp[numBytes - 1]; + do { + /* one loop per digit */ + digit = 0; + for(digitByte=0; digitByten before this break? */ + if(--numBytes == 0) { + break; + } + } + g->n[digitDex++] = digit; + } while (numBytes != 0); + + /* + * Infer sign from non-zero n[] elements + */ + g->sign = numDigits; + gtrimSign(g); +} +