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