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