1/* Copyright (c) 1998,2011-2012,2014 Apple 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, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
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 at Apple
18 *	Mods for variable size giantDigit.
19 * 	Rewrote serializeGiant(), deserializeGiant() to conform to IEEE P1363.
20 * 23 Mar 98 at Apple
21 *	Added FR_WrongSignatureType, FR_BadKeyBlob to frtnStrings.
22 *	Added initCryptKit().
23 * 19 Jan 98 at Apple
24 *	Added cStringToUc()
25 * 09 Jan 98 at Apple
26 *	Added non-FEE_DEBUG version of printGiantHex()
27 * 27 Jan 97 at NeXT
28 *	Addd serializeGiant(), deserializeGiant; Deleted data_to_giant()
29 * 12 Dec 96 at NeXT
30 *	Added byteRepTo{int,key,giant}().
31 *  2 Aug 96 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