]> git.saurik.com Git - apple/security.git/blob - AppleCSP/CryptKitCSP/CryptKitDER.cpp
82e03a7246b7218f3051b520fc29f11315415b62
[apple/security.git] / AppleCSP / CryptKitCSP / CryptKitDER.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 * CryptKitDER.h - snacc-based routines to create and parse DER-encoded FEE
21 * keys and signatures
22 *
23 * Created 3/12/2001 by dmitch.
24 */
25
26 #ifdef CRYPTKIT_CSP_ENABLE
27
28 #include <Security/asn-incl.h>
29 #include <Security/sm_vdatypes.h>
30 #include <CryptKit/CryptKitDER.h>
31 #include <CryptKit/falloc.h>
32 #include <CryptKit/feeDebug.h>
33 #include <CryptKit/feeFunctions.h>
34 #include <Security/cdsaUtils.h>
35 #include <Security/appleoids.h>
36
37 #define PRINT_SIG_GIANTS 0
38 #define PRINT_CURVE_PARAMS 0
39 #define PRINT_SIZES 0
40 #if PRINT_SIZES
41 #define szprint(s) printf s
42 #else
43 #define szprint(s)
44 #endif
45
46 /*
47 * Trivial exception class associated with a feeReturn.
48 */
49 // @@@ This should really be a subclass of exception
50 class feeException
51 {
52 protected:
53 feeException(feeReturn frtn, const char *op);
54 public:
55 ~feeException() throw() {}
56 feeReturn frtn() const throw() { return mFrtn; }
57 static void throwMe(feeReturn frtn, const char *op = NULL) __attribute__((noreturn));
58 private:
59 feeReturn mFrtn;
60 };
61
62 feeException::feeException(
63 feeReturn frtn,
64 const char *op)
65 : mFrtn(frtn)
66 {
67 if(op) {
68 dbgLog(("%s: %s\n", op, feeReturnString(frtn)));
69 }
70 }
71
72 void feeException::throwMe(feeReturn frtn, const char *op = NULL) { throw feeException(frtn, op); }
73
74 /*
75 * ASN1 encoding rules specify that an integer's sign is indicated by the MSB
76 * of the first (MS) content byte. For a non-negative number, if the MSB of
77 * the MS byte (of the unencoded number) is one, then the encoding starts with
78 * a byte of zeroes to indicate positive sign. For a negative number, the first
79 * nine bits can not be all 1 - if they are (in the undecoded number), leading
80 * bytes of 0xff are trimmed off until the first nine bits are something other
81 * than one. Also, the first nine bits of the encoded number can not all be
82 * zero.
83 *
84 * CryptKit giants express their sign as part of the giantstruct.sign field.
85 * The giantDigit array (giantstruct.n[]) is stored l.s. digit first.
86 *
87 * These routines are independent of platform, endianness, and giatn digit size.
88 */
89
90 /* routines to guess maximum size of DER-encoded objects */
91 static unsigned feeSizeOfSnaccGiant(
92 giant g)
93 {
94 unsigned rtn = abs(g->sign) * GIANT_BYTES_PER_DIGIT;
95 szprint(("feeSizeOfSnaccGiant: sign %d size %d\n", g->sign, rtn + 4));
96 return rtn + 4;
97 }
98
99 static unsigned feeSizeofSnaccInt()
100 {
101 return 7;
102 }
103
104 /* PUBLIC... */
105 unsigned feeSizeOfDERSig(
106 giant g1,
107 giant g2)
108 {
109 unsigned rtn = feeSizeOfSnaccGiant(g1);
110 rtn += feeSizeOfSnaccGiant(g2);
111 szprint(("feeSizeOfDERSig: size %d\n", rtn + 4));
112 return rtn + 4;
113 }
114
115 static unsigned feeSizeofSnaccCurveParams(const curveParams *cp)
116 {
117 unsigned rtn = 5 * feeSizeofSnaccInt(); // primeType, curveType, q, k, m
118 rtn += 10 * feeSizeOfSnaccGiant(cp->basePrime);
119 szprint(("feeSizeofSnaccCurveParams: size %d\n", rtn));
120 return rtn;
121 }
122
123 static unsigned feeSizeOfSnaccPubKey(const curveParams *cp)
124 {
125 unsigned rtn = 11; // version plus sequence overhead
126 rtn += feeSizeofSnaccCurveParams(cp);
127 rtn += (3 * feeSizeOfSnaccGiant(cp->basePrime));
128 szprint(("feeSizeOfSnaccPubKey: size %d\n", rtn));
129 return rtn;
130 }
131
132 static unsigned feeSizeOfSnaccPrivKey(const curveParams *cp)
133 {
134 unsigned rtn = 11; // version plus sequence overhead
135 rtn += feeSizeofSnaccCurveParams(cp);
136 rtn += feeSizeOfSnaccGiant(cp->basePrime);
137 szprint(("feeSizeOfSnaccPrivKey: size %d\n", rtn));
138 return rtn;
139 }
140
141 /* perform 2's complement of byte array, expressed MS byte first */
142 static void twosComplement(
143 unsigned char *bytePtr, // points to MS byte
144 unsigned numBytes)
145 {
146 unsigned char *outp = bytePtr + numBytes - 1;
147 unsigned char carry = 1; // first time thru, carry = 1 to add one to 1's comp
148 for(unsigned byteDex=0; byteDex<numBytes; byteDex++) {
149 /* first complement, then add carry */
150 *outp = ~*outp + carry;
151 if(carry && (*outp == 0)) {
152 /* overflow/carry */
153 carry = 1;
154 }
155 else {
156 carry = 0;
157 }
158 outp--;
159 }
160 }
161
162 /*
163 * Convert a BigIntegerStr to a (mallocd) giant.
164 * Only known exception is a feeException.
165 */
166 static giant bigIntStrToGiant(
167 BigIntegerStr &bigInt)
168 {
169 char *rawOcts = bigInt;
170 unsigned numBytes = bigInt.Len();
171 unsigned numGiantDigits;
172 int sign = 1;
173 giant grtn;
174 feeReturn frtn = FR_Success;
175 unsigned char *inp = NULL;
176 unsigned digitDex; // index into g->giantDigit[]
177
178 /* handle degenerate case (value of zero) */
179 if((numBytes == 0) || ((numBytes == 1) && rawOcts[0] == 0)) {
180 grtn = newGiant(1);
181 if(grtn == NULL) {
182 feeException::throwMe(FR_Memory, "newGiant(1)");
183 }
184 int_to_giant(0, grtn);
185 return grtn;
186 }
187
188 /* make a copy of raw octets if we have to do two's complement */
189 unsigned char *byteArray = NULL;
190 bool didMalloc = false;
191 if(rawOcts[0] & 0x80) {
192 sign = -1;
193 numBytes++;
194 byteArray = (unsigned char *)fmalloc(numBytes);
195 didMalloc = true;
196 byteArray[0] = 0xff;
197 memmove(byteArray + 1, rawOcts, numBytes-1);
198 twosComplement(byteArray, numBytes);
199 }
200 else {
201 /* no copy */
202 char *foo = rawOcts;
203 byteArray = (unsigned char *)foo;
204 }
205
206 /* cook up a new giant */
207 numGiantDigits = (numBytes + GIANT_BYTES_PER_DIGIT - 1) /
208 GIANT_BYTES_PER_DIGIT;
209 grtn = newGiant(numGiantDigits);
210 if(grtn == NULL) {
211 frtn = FR_Memory;
212 goto abort;
213 }
214
215 /*
216 * Convert byteArray to array of giantDigits
217 * inp - raw input bytes, LSB last
218 * grtn->n[] - output array of giantDigits, LSD first
219 * Start at LS byte and LD digit
220 */
221 digitDex = 0; // index into g->giantDigit[]
222 giantDigit thisDigit;
223 inp = byteArray + numBytes - 1;
224 unsigned dex; // total byte counter
225 unsigned byteDex; // index into one giantDigit
226 unsigned shiftCount;
227 for(dex=0; dex<numBytes; ) { // increment dex inside
228 thisDigit = 0;
229 shiftCount = 0;
230 for(byteDex=0; byteDex<GIANT_BYTES_PER_DIGIT; byteDex++) {
231 thisDigit |= ((giantDigit)(*inp--) << shiftCount);
232 shiftCount += 8;
233 if(++dex == numBytes) {
234 /* must be partial giantDigit */
235 break;
236 }
237 }
238 CKASSERT(digitDex < numGiantDigits);
239 grtn->n[digitDex++] = thisDigit;
240 }
241 grtn->sign = (int)numGiantDigits * sign;
242
243 /* trim leading (MS) zeroes */
244 gtrimSign(grtn);
245 abort:
246 if(didMalloc) {
247 ffree(byteArray);
248 }
249 if(frtn) {
250 feeException::throwMe(frtn, "bigIntStrToGiant");
251 }
252 return grtn;
253 }
254
255 /*
256 * Convert a giant to an existing BigIntegerString.
257 * Only known exception is a feeException.
258 */
259 static void giantToBigIntStr(
260 giant g,
261 BigIntegerStr &bigInt)
262 {
263 unsigned char doPrepend = 0;
264 unsigned numGiantDigits = abs(g->sign);
265 unsigned numBytes = numGiantDigits * GIANT_BYTES_PER_DIGIT;
266 giantDigit msGiantBit = 0;
267 if(isZero(g)) {
268 /* special degenerate case */
269 bigInt.ReSet("", 1);
270 return;
271 }
272 else {
273 msGiantBit = g->n[numGiantDigits - 1] >> (GIANT_BITS_PER_DIGIT - 1);
274 }
275
276 /* prepend a byte of zero if necessary */
277 if((g->sign < 0) || // negative - to handle 2's complement
278 ((g->sign > 0) && msGiantBit)) { // ensure MS byte is zero
279 doPrepend = 1;
280 numBytes++;
281 }
282
283 unsigned char *rawBytes = (unsigned char *)fmalloc(numBytes);
284 if(rawBytes == NULL) {
285 feeException::throwMe(FR_Memory, "giantToBigIntStr fmalloc(rawBytes)");
286 }
287 unsigned char *outp = rawBytes;
288 if(doPrepend) {
289 *outp++ = 0;
290 }
291
292 /*
293 * Convert array of giantDigits to bytes.
294 * outp point to MS output byte.
295 */
296 int digitDex; // index into g->giantDigit[]
297 unsigned byteDex; // byte index into a giantDigit
298 for(digitDex=numGiantDigits-1; digitDex>=0; digitDex--) {
299 /* one loop per giantDigit, starting at MS end */
300 giantDigit thisDigit = g->n[digitDex];
301 unsigned char *bp = outp + GIANT_BYTES_PER_DIGIT - 1;
302 for(byteDex=0; byteDex<GIANT_BYTES_PER_DIGIT; byteDex++) {
303 /* one loop per byte within the digit, starting at LS end */
304 *bp-- = (unsigned char)(thisDigit) & 0xff;
305 thisDigit >>= 8;
306 }
307 outp += GIANT_BYTES_PER_DIGIT;
308 }
309
310 /* do two's complement for negative giants */
311 if(g->sign < 0) {
312 twosComplement(rawBytes, numBytes);
313 }
314
315 /* strip off redundant leading bits (nine zeroes or nine ones) */
316 outp = rawBytes;
317 unsigned char *endp = outp + numBytes - 1;
318 while((*outp == 0) && // m.s. byte zero
319 (outp < endp) && // more bytes exist
320 (!(outp[1] & 0x80))) { // 9th bit is 0
321 outp++;
322 numBytes--;
323 }
324 while((*outp == 0xff) && // m.s. byte all ones
325 (outp < endp) && // more bytes exist
326 (outp[1] & 0x80)) { // 9th bit is 1
327 outp++;
328 numBytes--;
329 }
330
331 /* rawBytes are the ASN-compliant contents */
332 bigInt.ReSet(reinterpret_cast<const char *>(outp), numBytes);
333 ffree(rawBytes);
334 }
335
336 /* curveParams : CryptKit <--> snacc */
337 /* Only known exception is a feeException */
338 static FEECurveParameters *feeCurveParamsToSnacc(
339 const curveParams *cp)
340 {
341 #if PRINT_CURVE_PARAMS
342 printf("===encoding curveParams; cp:\n"); printCurveParams(cp);
343 #endif
344 FEECurveParameters *snaccCp = NULL;
345 try {
346 snaccCp = new FEECurveParameters();
347 AsnIntType val;
348 switch(cp->primeType) {
349 case FPT_Mersenne:
350 val = FEEPrimeType::pt_mersenne;
351 break;
352 case FPT_FEE:
353 val = FEEPrimeType::pt_fee;
354 break;
355 case FPT_General:
356 val = FEEPrimeType::pt_general;
357 break;
358 default:
359 feeException::throwMe(FR_Internal, "bad cp->primeType");
360 }
361 snaccCp->primeType.Set(val);
362 switch(cp->curveType) {
363 case FCT_Montgomery:
364 val = FEECurveType::ct_montgomery;
365 break;
366 case FCT_Weierstrass:
367 val = FEECurveType::ct_weierstrass;
368 break;
369 case FCT_General:
370 val = FEECurveType::ct_general;
371 break;
372 default:
373 feeException::throwMe(FR_Internal, "bad cp->curveType");
374 }
375 snaccCp->curveType.Set(val);
376 snaccCp->q.Set(cp->q);
377 snaccCp->k.Set(cp->k);
378 snaccCp->m.Set(cp->m);
379 giantToBigIntStr(cp->a, snaccCp->a);
380 giantToBigIntStr(cp->b, snaccCp->bb);
381 giantToBigIntStr(cp->c, snaccCp->c);
382 giantToBigIntStr(cp->x1Plus, snaccCp->x1Plus);
383 giantToBigIntStr(cp->x1Minus, snaccCp->x1Minus);
384 giantToBigIntStr(cp->cOrderPlus, snaccCp->cOrderPlus);
385 giantToBigIntStr(cp->cOrderMinus, snaccCp->cOrderMinus);
386 giantToBigIntStr(cp->x1OrderPlus, snaccCp->x1OrderPlus);
387 giantToBigIntStr(cp->x1OrderMinus, snaccCp->x1OrderMinus);
388 if(cp->primeType == FPT_General) {
389 snaccCp->basePrime = new BigIntegerStr();
390 giantToBigIntStr(cp->basePrime, *snaccCp->basePrime);
391 }
392 }
393 catch(const feeException &ferr) {
394 delete snaccCp;
395 throw;
396 }
397 catch(...) {
398 delete snaccCp;
399 feeException::throwMe(FR_Memory, "feeCurveParamsToSnacc catchall"); // ???
400 }
401 return snaccCp;
402 }
403
404 static curveParams *feeCurveParamsFromSnacc(
405 FEECurveParameters &snaccCp)
406 {
407 curveParams *cp = newCurveParams();
408 if(cp == NULL) {
409 feeException::throwMe(FR_Memory, "feeCurveParamsFromSnacc alloc cp");
410 }
411 AsnIntType val = snaccCp.primeType;
412 switch(val) {
413 case FEEPrimeType::pt_mersenne:
414 cp->primeType = FPT_Mersenne;
415 break;
416 case FEEPrimeType::pt_fee:
417 cp->primeType = FPT_FEE;
418 break;
419 case FEEPrimeType::pt_general:
420 cp->primeType = FPT_General;
421 break;
422 default:
423 feeException::throwMe(FR_BadPubKey, "feeCurveParamsFromSnacc bad primeType");
424 }
425 val = snaccCp.curveType;
426 switch(val) {
427 case FEECurveType::ct_montgomery:
428 cp->curveType = FCT_Montgomery;
429 break;
430 case FEECurveType::ct_weierstrass:
431 cp->curveType = FCT_Weierstrass;
432 break;
433 case FEECurveType::ct_general:
434 cp->curveType = FCT_General;
435 break;
436 default:
437 feeException::throwMe(FR_BadPubKey, "feeCurveParamsFromSnacc bad curveType");
438 }
439 cp->q = snaccCp.q;
440 cp->k = snaccCp.k;
441 cp->m = snaccCp.m;
442 cp->a = bigIntStrToGiant(snaccCp.a);
443 cp->b = bigIntStrToGiant(snaccCp.bb);
444 cp->c = bigIntStrToGiant(snaccCp.c);
445 cp->x1Plus = bigIntStrToGiant(snaccCp.x1Plus);
446 cp->x1Minus = bigIntStrToGiant(snaccCp.x1Minus);
447 cp->cOrderPlus = bigIntStrToGiant(snaccCp.cOrderPlus);
448 cp->cOrderMinus = bigIntStrToGiant(snaccCp.cOrderMinus);
449 cp->x1OrderPlus = bigIntStrToGiant(snaccCp.x1OrderPlus);
450 cp->x1OrderMinus = bigIntStrToGiant(snaccCp.x1OrderMinus);
451 if(snaccCp.basePrime != NULL) {
452 cp->basePrime = bigIntStrToGiant(*snaccCp.basePrime);
453 }
454
455 /* remaining fields inferred */
456 curveParamsInferFields(cp);
457 allocRecipGiants(cp);
458 #if PRINT_CURVE_PARAMS
459 printf("===decoding curveParams; cp:\n"); printCurveParams(cp);
460 #endif
461 return cp;
462 }
463
464 /***
465 *** Public routines. These are usable from C code; they never throw.
466 ***/
467
468 /*
469 * Encode/decode the two FEE signature types. We malloc returned data via
470 * fmalloc(); caller must free via ffree().
471 */
472 feeReturn feeDEREncodeElGamalSignature(
473 giant u,
474 giant PmX,
475 unsigned char **encodedSig, // fmallocd and RETURNED
476 unsigned *encodedSigLen) // RETURNED
477 {
478 FEEElGamalSignature snaccSig;
479 CssmAutoData oData(CssmAllocator::standard(CssmAllocator::sensitive));
480
481 try {
482 giantToBigIntStr(u, snaccSig.u);
483 giantToBigIntStr(PmX, snaccSig.pmX);
484 }
485 catch(const feeException &ferr) {
486 return ferr.frtn();
487 }
488 try {
489 SC_encodeAsnObj(snaccSig, oData, feeSizeOfDERSig(u, PmX));
490 }
491 catch(...) {
492 /* FIXME - bad sig? memory? */
493 return FR_BadSignatureFormat;
494 }
495 *encodedSig = (unsigned char *)fmalloc(oData.length());
496 *encodedSigLen = oData.length();
497 memmove(*encodedSig, oData.get().Data, oData.length());
498 #if PRINT_SIG_GIANTS
499 printf("feeEncodeElGamalSignature:\n");
500 printf(" u : "); printGiantHex(u);
501 printf(" PmX : "); printGiantHex(PmX);
502 printf(" u : "); snaccSig.u.Print(cout); printf("\n");
503 printf(" PmX : "); snaccSig.pmX.Print(cout); printf("\n");
504 #endif
505 return FR_Success;
506 }
507
508 feeReturn feeDEREncodeECDSASignature(
509 giant c,
510 giant d,
511 unsigned char **encodedSig, // fmallocd and RETURNED
512 unsigned *encodedSigLen) // RETURNED
513 {
514 FEEECDSASignature snaccSig;
515 CssmAutoData oData(CssmAllocator::standard(CssmAllocator::sensitive));
516
517 try {
518 giantToBigIntStr(c, snaccSig.c);
519 giantToBigIntStr(d, snaccSig.d);
520 }
521 catch(const feeException &ferr) {
522 return ferr.frtn();
523 }
524 try {
525 SC_encodeAsnObj(snaccSig, oData, feeSizeOfDERSig(c, d));
526 }
527 catch(...) {
528 /* FIXME - bad sig? memory? */
529 return FR_BadSignatureFormat;
530 }
531 *encodedSig = (unsigned char *)fmalloc(oData.length());
532 *encodedSigLen = oData.length();
533 memmove(*encodedSig, oData.get().Data, oData.length());
534 #if PRINT_SIG_GIANTS
535 printf("feeEncodeECDSASignature:\n");
536 printf(" c : "); printGiantHex(*c);
537 printf(" d : "); printGiantHex(*d);
538 printf(" c : "); snaccSig.c.Print(cout); printf("\n");
539 printf(" d : "); snaccSig.d.Print(cout); printf("\n");
540 #endif
541 return FR_Success;
542 }
543
544 feeReturn feeDERDecodeElGamalSignature(
545 const unsigned char *encodedSig,
546 unsigned encodedSigLen,
547 giant *u, // newGiant'd and RETURNED
548 giant *PmX) // newGiant'd and RETURNED
549 {
550 FEEElGamalSignature snaccSig;
551 CssmData cData((void *)encodedSig, encodedSigLen);
552 try {
553 SC_decodeAsnObj(cData, snaccSig);
554 }
555 catch(...) {
556 return FR_BadSignatureFormat;
557 }
558 try {
559 *u = bigIntStrToGiant(snaccSig.u);
560 *PmX = bigIntStrToGiant(snaccSig.pmX);
561 }
562 catch(const feeException &ferr) {
563 return ferr.frtn();
564 }
565 catch(...) {
566 /* FIXME - bad sig? memory? */
567 return FR_Memory;
568 }
569 #if PRINT_SIG_GIANTS
570 printf("feeDecodeElGamalSignature:\n");
571 printf(" u : "); printGiantHex(*u);
572 printf(" PmX : "); printGiantHex(*PmX);
573 printf(" u : "); snaccSig.u.Print(cout); printf("\n");
574 printf(" PmX : "); snaccSig.pmX.Print(cout); printf("\n");
575 #endif
576 return FR_Success;
577 }
578
579 feeReturn feeDERDecodeECDSASignature(
580 const unsigned char *encodedSig,
581 unsigned encodedSigLen,
582 giant *c, // newGiant'd and RETURNED
583 giant *d) // newGiant'd and RETURNED
584 {
585 FEEECDSASignature snaccSig;
586 CssmData cData((void *)encodedSig, encodedSigLen);
587 try {
588 SC_decodeAsnObj(cData, snaccSig);
589 }
590 catch(...) {
591 return FR_BadSignatureFormat;
592 }
593 try {
594 *c = bigIntStrToGiant(snaccSig.c);
595 *d = bigIntStrToGiant(snaccSig.d);
596 }
597 catch(const feeException &ferr) {
598 return ferr.frtn();
599 }
600 catch(...) {
601 /* FIXME - bad sig? memory? */
602 return FR_Memory;
603 }
604 #if PRINT_SIG_GIANTS
605 printf("feeDecodeECDSASignature:\n");
606 printf(" c : "); printGiantHex(*c);
607 printf(" d : "); printGiantHex(*d);
608 printf(" c : "); snaccSig.c.Print(cout); printf("\n");
609 printf(" d : "); snaccSig.d.Print(cout); printf("\n");
610 #endif
611 return FR_Success;
612 }
613
614 /*
615 * Encode/decode the FEE private and public keys. We malloc returned data via
616 * falloc(); caller must free via ffree(). Public C functions which never throw.
617 */
618 feeReturn feeDEREncodePublicKey(
619 int version,
620 const curveParams *cp,
621 giant plusX,
622 giant minusX,
623 giant plusY, // may be NULL
624 unsigned char **keyBlob, // fmallocd and RETURNED
625 unsigned *keyBlobLen) // RETURNED
626 {
627 FEEPublicKey snaccKey;
628
629 /* set up the SNACC object */
630 snaccKey.version.Set(version);
631 try {
632 snaccKey.curveParams = feeCurveParamsToSnacc(cp);
633 giantToBigIntStr(plusX, snaccKey.plusX);
634 giantToBigIntStr(minusX, snaccKey.minusX);
635 if(plusY != NULL) {
636 snaccKey.plusY = new BigIntegerStr();
637 giantToBigIntStr(plusY, *snaccKey.plusY);
638 }
639 }
640 catch(const feeException &ferr) {
641 return ferr.frtn();
642 }
643
644 /* encode the SNACC object */
645 CssmAutoData oData(CssmAllocator::standard(CssmAllocator::sensitive));
646
647 try {
648 SC_encodeAsnObj(snaccKey, oData, feeSizeOfSnaccPubKey(cp));
649 }
650 catch(...) {
651 /* FIXME - ???? */
652 return FR_Memory;
653 }
654 *keyBlob = (unsigned char *)fmalloc(oData.length());
655 *keyBlobLen = oData.length();
656 memmove(*keyBlob, oData.get().Data, oData.length());
657 return FR_Success;
658 }
659
660 feeReturn feeDEREncodePrivateKey(
661 int version,
662 const curveParams *cp,
663 const giant privData,
664 unsigned char **keyBlob, // fmallocd and RETURNED
665 unsigned *keyBlobLen) // RETURNED
666 {
667 FEEPrivateKey snaccKey;
668
669 /* set up the SNACC object */
670 snaccKey.version.Set(version);
671 try {
672 snaccKey.curveParams = feeCurveParamsToSnacc(cp);
673 giantToBigIntStr(privData, snaccKey.privData);
674 }
675 catch(const feeException &ferr) {
676 return ferr.frtn();
677 }
678
679 /* encode the SNACC object */
680 CssmAutoData oData(CssmAllocator::standard(CssmAllocator::sensitive));
681
682 try {
683 SC_encodeAsnObj(snaccKey, oData, feeSizeOfSnaccPrivKey(cp));
684 }
685 catch(...) {
686 /* FIXME - ???? */
687 return FR_Memory;
688 }
689 *keyBlob = (unsigned char *)fmalloc(oData.length());
690 *keyBlobLen = oData.length();
691 memmove(*keyBlob, oData.get().Data, oData.length());
692 return FR_Success;
693 }
694
695 feeReturn feeDERDecodePublicKey(
696 const unsigned char *keyBlob,
697 unsigned keyBlobLen,
698 int *version, // this and remainder RETURNED
699 curveParams **cp,
700 giant *plusX,
701 giant *minusX,
702 giant *plusY) // may be NULL
703 {
704 FEEPublicKey snaccKey;
705 CssmData cData((unsigned char *)keyBlob, (size_t)keyBlobLen);
706 try {
707 SC_decodeAsnObj(cData, snaccKey);
708 }
709 catch(...) {
710 return FR_BadPubKey;
711 }
712 try {
713 *version = snaccKey.version;
714 *cp = feeCurveParamsFromSnacc(*snaccKey.curveParams);
715 *plusX = bigIntStrToGiant(snaccKey.plusX);
716 *minusX = bigIntStrToGiant(snaccKey.minusX);
717 if(snaccKey.plusY != NULL) {
718 /* optional */
719 *plusY = bigIntStrToGiant(*snaccKey.plusY);
720 }
721 else {
722 *plusY = newGiant(1);
723 int_to_giant(0, *plusY);
724 }
725 }
726 catch(const feeException &ferr) {
727 return ferr.frtn();
728 }
729 catch(...) {
730 /* FIXME - bad sig? memory? */
731 return FR_Memory;
732 }
733 return FR_Success;
734 }
735
736 feeReturn feeDERDecodePrivateKey(
737 const unsigned char *keyBlob,
738 unsigned keyBlobLen,
739 int *version, // this and remainder RETURNED
740 curveParams **cp,
741 giant *privData) // RETURNED
742 {
743 FEEPrivateKey snaccKey;
744 CssmData cData((unsigned char *)keyBlob, (size_t)keyBlobLen);
745 try {
746 SC_decodeAsnObj(cData, snaccKey);
747 }
748 catch(...) {
749 return FR_BadPubKey;
750 }
751 try {
752 *version = snaccKey.version;
753 *cp = feeCurveParamsFromSnacc(*snaccKey.curveParams);
754 *privData = bigIntStrToGiant(snaccKey.privData);
755 }
756 catch(const feeException &ferr) {
757 return ferr.frtn();
758 }
759 catch(...) {
760 /* FIXME - bad sig? memory? */
761 return FR_Memory;
762 }
763 return FR_Success;
764 }
765
766 #endif /* CRYPTKIT_CSP_ENABLE */