1/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. 2 * 3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT 4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE 5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE 6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, 7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL 8 * EXPOSE YOU TO LIABILITY. 9 *************************************************************************** 10 * 11 * ckutilities.c - general C routines 12 * 13 * Revision History 14 * ---------------- 15 * 10/06/98 ap 16 * Changed to compile with C++. 17 * 08 Apr 98 Doug Mitchell at Apple 18 * Mods for variable size giantDigit. 19 * Rewrote serializeGiant(), deserializeGiant() to conform to IEEE P1363. 20 * 23 Mar 98 Doug Mitchell at Apple 21 * Added FR_WrongSignatureType, FR_BadKeyBlob to frtnStrings. 22 * Added initCryptKit(). 23 * 19 Jan 98 Doug Mitchell at Apple 24 * Added cStringToUc() 25 * 09 Jan 98 Doug Mitchell at Apple 26 * Added non-FEE_DEBUG version of printGiantHex() 27 * 27 Jan 97 Doug Mitchell at NeXT 28 * Addd serializeGiant(), deserializeGiant; Deleted data_to_giant() 29 * 12 Dec 96 Doug Mitchell at NeXT 30 * Added byteRepTo{int,key,giant}(). 31 * 2 Aug 96 Doug Mitchell at NeXT 32 * Broke out from Blaine Garst's original NSCryptors.m 33 */ 34 35#include "ckutilities.h" 36#include "falloc.h" 37#include "feeTypes.h" 38#include "feeDebug.h" 39#include "feeFunctions.h" 40#include "byteRep.h" 41#include "platform.h" 42#include "curveParams.h" 43#include <stdlib.h> 44#ifdef NeXT 45#include <libc.h> 46#include <stdio.h> 47#include <signal.h> 48#include <sgtty.h> 49#endif // NeXT 50 51/* 52 * feeReturn strings. 53 */ 54typedef struct { 55 feeReturn frtn; 56 const char *frtnString; 57} frtnItem; 58 59static const frtnItem frtnStrings[] = { 60#ifndef NDEBUG 61 { FR_Success, "Success" }, 62 { FR_BadPubKey, "Bad Public Key" }, 63 { FR_BadPubKeyString, "Bad Public Key String" }, 64 { FR_IncompatibleKey, "Incompatible key format" }, 65 { FR_IllegalDepth, "Illegal Depth" }, 66 { FR_BadUsageName, "Bad Usage Name" }, 67 { FR_BadSignatureFormat, "Bad Signature Format" }, 68 { FR_InvalidSignature, "Invalid Signature" }, 69 { FR_IllegalArg, "Illegal Argument" }, 70 { FR_BadCipherText, "Bad Ciphertext Format" }, 71 { FR_Unimplemented, "Unimplemented Function" }, 72 { FR_BadCipherFile, "Bad CipherFile Format" }, 73 { FR_BadEnc64, "Bad enc64 Format" }, 74 { FR_WrongSignatureType, "Wrong Signature Type" }, 75 { FR_BadKeyBlob, "Bad Key Blob" }, 76 { FR_IllegalCurve, "Bad curve type" }, 77 { FR_Internal, "Internal Library Error" }, 78 { FR_Memory, "Out of Memory" }, 79 { FR_ShortPrivData, "Insufficient Seed Data" }, 80#endif /* NDEBUG */ 81 { (feeReturn) 0, NULL }, 82}; 83 84/* 85 * One-time only init of CryptKit library. 86 */ 87void initCryptKit(void) 88{ 89 #if GIANTS_VIA_STACK 90 curveParamsInitGiants(); 91 #endif 92} 93 94/* 95 * Shutdown. 96 */ 97void terminateCryptKit(void) 98{ 99 #if GIANTS_VIA_STACK 100 freeGiantStacks(); 101 #endif 102} 103 104/* 105 * Create a giant, initialized with specified char[] data. 106 */ 107giant giant_with_data(const unsigned char *d, int len) { 108 int numDigits = BYTES_TO_GIANT_DIGITS(len); 109 giant result; 110 111 result = newGiant(numDigits); 112 deserializeGiant(d, result, len); 113 return result; 114} 115 116/* 117 * Obtain a malloc'd memory chunk init'd with specified giant's data. 118 * Resulting bytes are portable. Size of malloc'd memory is always zero 119 * mod GIANT_BYTES_PER_DIGIT. 120 * 121 * Calling this function for a giant obtained by giant_with_data() yields 122 * the original data, with extra byte(s) of leading zeros if the original 123 * was not zero mod GIANT_BYTES_PER_DIGIT. 124 */ 125unsigned char *mem_from_giant(giant g, 126 unsigned *memLen) /* RETURNED size of malloc'd region */ 127{ 128 unsigned char *cp; 129 unsigned numDigits = (g->sign < 0) ? -g->sign : g->sign; 130 131 *memLen = numDigits * GIANT_BYTES_PER_DIGIT; 132 cp = (unsigned char*) fmalloc(*memLen); 133 serializeGiant(g, cp, *memLen); 134 return cp; 135} 136 137extern const char *feeReturnString(feeReturn frtn) 138{ 139 const frtnItem *fi = frtnStrings; 140 141 while(fi->frtnString) { 142 if(fi->frtn == frtn) { 143 return fi->frtnString; 144 } 145 fi++; 146 } 147 return "Unknown Status"; 148} 149 150#if FEE_DEBUG 151void printGiant(const giant x) 152{ 153 int i; 154 155 printf("sign=%d cap=%d n[]=", x->sign, x->capacity); 156 for(i=0; i<abs(x->sign); i++) { 157 printf("%u:", x->n[i]); 158 } 159 printf("\n"); 160} 161 162void printGiantHex(const giant x) 163{ 164 int i; 165 166 printf("sign=%d cap=%d n[]=", x->sign, x->capacity); 167 for(i=0; i<abs(x->sign); i++) { 168 printf("%x:", x->n[i]); 169 } 170 printf("\n"); 171} 172 173/* 174 * Print in the form 175 * sign=8 cap=16 n[]=29787 + 3452 * w^1 + 55260 * w^2 + ... 176 */ 177void printGiantExp(const giant x) 178{ 179 int i; 180 int size = abs(x->sign); 181 182 printf("sign=%d cap=%d n[]=", x->sign, x->capacity); 183 for(i=0; i<size; i++) { 184 printf("%u ", x->n[i]); 185 if(i > 0) { 186 printf("* w^%d ", i); 187 } 188 if(i<(size-1)) { 189 printf("+ "); 190 } 191 } 192 printf("\n"); 193} 194 195void printKey(const key k) 196{ 197 printf(" twist %d\n", k->twist); 198 printf(" x: "); 199 printGiant(k->x); 200} 201 202void printCurveParams(const curveParams *p) 203{ 204 const char *pt; 205 const char *ct; 206 207 switch(p->primeType) { 208 case FPT_Mersenne: 209 pt = "FPT_Mersenne"; 210 break; 211 case FPT_FEE: 212 pt = "FPT_FEE"; 213 break; 214 case FPT_General: 215 pt = "FPT_General"; 216 break; 217 default: 218 pt = "UNKNOWN!"; 219 break; 220 } 221 switch(p->curveType) { 222 case FCT_Montgomery: 223 ct = "FCT_Montgomery"; 224 break; 225 case FCT_Weierstrass: 226 ct = "FCT_Weierstrass"; 227 break; 228 case FCT_General: 229 ct = "FCT_General"; 230 break; 231 default: 232 ct = "UNKNOWN!"; 233 break; 234 } 235 printf(" q %d k %d primeType %s curveType %s\n", 236 p->q, p->k, pt, ct); 237 printf(" minBytes %d maxDigits %d\n", p->minBytes, p->maxDigits); 238 printf(" a : "); 239 printGiant(p->a); 240 printf(" b : "); 241 printGiant(p->b); 242 printf(" c : "); 243 printGiant(p->c); 244 printf(" basePrime : "); 245 printGiant(p->basePrime); 246 printf(" x1Plus : "); 247 printGiant(p->x1Plus); 248 printf(" x1Minus : "); 249 printGiant(p->x1Minus); 250 printf(" cOrderPlus : "); 251 printGiant(p->cOrderPlus); 252 printf(" cOrderMinus : "); 253 printGiant(p->cOrderMinus); 254 printf(" x1OrderPlus : "); 255 printGiant(p->x1OrderPlus); 256 printf(" x1OrderMinus: "); 257 printGiant(p->x1OrderMinus); 258} 259#else 260void printGiant(const giant x) {} 261void printGiantHex(const giant x) {} 262void printGiantExp(const giant x) {} 263void printKey(const key k) {} 264void printCurveParams(const curveParams *p) {} 265 266#endif /* FEE_DEBUG */ 267 268#if defined(NeXT) && !defined(WIN32) 269 270void getpassword(const char *prompt, char *pbuf) 271{ 272 struct sgttyb ttyb; 273 int flags; 274 register char *p; 275 register int c; 276 FILE *fi; 277 void (*sig)(int); 278 279 if ((fi = fdopen(open("/dev/tty", 2, 0), "r")) == NULL) 280 fi = stdin; 281 else 282 setbuf(fi, (char *)NULL); 283 sig = signal(SIGINT, SIG_IGN); 284 ioctl(fileno(fi), TIOCGETP, &ttyb); 285 flags = ttyb.sg_flags; 286 ttyb.sg_flags &= ~ECHO; 287 ioctl(fileno(fi), TIOCSETP, &ttyb); 288 fprintf(stderr, "%s", prompt); fflush(stderr); 289 for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) { 290 if (p < &pbuf[PHRASELEN-1]) 291 *p++ = c; 292 } 293 *p = '\0'; 294 fprintf(stderr, "\n"); fflush(stderr); 295 ttyb.sg_flags = flags; 296 ioctl(fileno(fi), TIOCSETP, &ttyb); 297 (void)signal(SIGINT, sig); 298 if (fi != stdin) 299 fclose(fi); 300} 301#endif // NeXT 302 303/* 304 * serialize, deserialize giants's n[] to/from byte stream. 305 * First byte of byte stream is the MS byte of the resulting giant, 306 * regardless of the size of giantDigit. 307 * 308 * No assumption is made about the alignment of cp. 309 * 310 * As of 7 Apr 1998, these routines are in compliance with IEEE P1363, 311 * section 5.5.1, for the representation of a large integer as a byte 312 * stream. 313 */ 314void serializeGiant(giant g, 315 unsigned char *cp, 316 unsigned numBytes) 317{ 318 unsigned digitDex; 319 unsigned numDigits = BYTES_TO_GIANT_DIGITS(numBytes); 320 giantDigit digit; 321 unsigned char *ptr; 322 unsigned digitByte; 323 int size = abs(g->sign); 324 325 if(numBytes == 0) { 326 return; 327 } 328 if(numBytes > (g->capacity * GIANT_BYTES_PER_DIGIT)) { 329 CKRaise("serializeGiant: CAPACITY EXCEEDED!\n"); 330 } 331 332 /* 333 * note we might be asked to write more than the valid number 334 * if bytes in the giant in the case if truncated sign due to 335 * zero M.S. digit(s).... 336 */ 337 338 /* 339 * zero out unused digits so we can infer sign during deserialize 340 */ 341 for(digitDex=size; digitDex<numDigits; digitDex++) { 342 g->n[digitDex] = 0; 343 } 344 345 /* 346 * Emit bytes starting from l.s. byte. L.s. byte of the outgoing 347 * data stream is *last*. L.s. digit of giant's digits is *first*. 348 */ 349 digitDex = 0; 350 ptr = &cp[numBytes - 1]; 351 do { 352 /* one loop per giant digit */ 353 digit = g->n[digitDex++]; 354 for(digitByte=0; digitByte<GIANT_BYTES_PER_DIGIT; digitByte++) { 355 /* one loop per byte in the digit */ 356 *ptr-- = (unsigned char)digit; 357 if(--numBytes == 0) { 358 break; 359 } 360 digit >>= 8; 361 } 362 } while(numBytes != 0); 363 364} 365 366/* 367 * Resulting sign here is always positive; leading zeroes are reflected 368 * in an altered g->sign. 369 */ 370void deserializeGiant(const unsigned char *cp, 371 giant g, 372 unsigned numBytes) 373{ 374 unsigned numDigits; 375 giantDigit digit; 376 int digitDex; 377 unsigned digitByte; 378 const unsigned char *ptr; 379 380 if(numBytes == 0) { 381 g->sign = 0; 382 return; 383 } 384 numDigits = (numBytes + GIANT_BYTES_PER_DIGIT - 1) / 385 GIANT_BYTES_PER_DIGIT; 386 if(numBytes > (g->capacity * GIANT_BYTES_PER_DIGIT)) { 387 CKRaise("deserializeGiant: CAPACITY EXCEEDED!\n"); 388 } 389 390 /* 391 * Start at l.s. byte. That's the end of the cp[] array and 392 * the beginning of the giantDigit array. 393 */ 394 digitDex = 0; 395 ptr = &cp[numBytes - 1]; 396 do { 397 /* one loop per digit */ 398 digit = 0; 399 for(digitByte=0; digitByte<GIANT_BYTES_PER_DIGIT; digitByte++) { 400 /* one loop per byte in the digit */ 401 digit |= (*ptr-- << (8 * digitByte)); 402 /* FIXME - shouldn't we update g->n before this break? */ 403 if(--numBytes == 0) { 404 break; 405 } 406 } 407 g->n[digitDex++] = digit; 408 } while (numBytes != 0); 409 410 /* 411 * Infer sign from non-zero n[] elements 412 */ 413 g->sign = numDigits; 414 gtrimSign(g); 415} 416 417