]> git.saurik.com Git - apple/security.git/blob - AppleCSP/open_ssl/opensslUtils/openRsaSnacc.cpp
Security-54.1.9.tar.gz
[apple/security.git] / AppleCSP / open_ssl / opensslUtils / openRsaSnacc.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 * openRsaSnacc.cpp - glue between openrsa and SNACC
21 */
22 #include "openRsaSnacc.h"
23 #include "opensslUtils.h"
24 #include <openssl/err.h>
25 #include <openssl/bn.h>
26 #include <openssl/crypto.h>
27
28 // bring in a ton of snacc-related stuff
29 #include <Security/asn-incl.h>
30 #include <Security/sm_vdatypes.h>
31
32 // snacc-generated - snacc really should place these in pkcs[78].h
33 #include <Security/sm_x501ud.h>
34 #include <Security/sm_x411ub.h>
35 #include <Security/sm_x411mtsas.h>
36 #include <Security/sm_x501if.h>
37 #include <Security/sm_x520sa.h>
38 #include <Security/sm_x509cmn.h>
39 #include <Security/sm_x509af.h>
40 #include <Security/sm_x509ce.h>
41 #include <Security/pkcs1oids.h>
42 #include <Security/pkcs9oids.h>
43 #include <Security/sm_cms.h>
44 #include <Security/sm_ess.h>
45 #include <Security/pkcs7.h>
46 #include <Security/pkcs8.h>
47
48 #include <Security/cdsaUtils.h>
49 #include <Security/debugging.h>
50 #include <Security/appleoids.h>
51
52
53 #define sslSnaccDebug(args...) debug("sslSnacc", ##args)
54
55 /*
56 * Convert between SNACC-style BigIntegerStr and openssl-style BIGNUM.
57 */
58 BIGNUM *bigIntStrToBn(
59 BigIntegerStr &snaccInt)
60 {
61 BIGNUM *bn = BN_new();
62 BIGNUM *rtn;
63 char *rawOcts = snaccInt;
64 unsigned numBytes = snaccInt.Len();
65
66 rtn = BN_bin2bn((unsigned char *)rawOcts, numBytes, bn);
67 if(rtn == NULL) {
68 BN_free(bn);
69 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
70 }
71 return bn;
72 }
73
74 void bnToBigIntStr(
75 BIGNUM *bn,
76 BigIntegerStr &snaccInt)
77 {
78 unsigned numBytes = BN_num_bytes(bn);
79 unsigned char *buf;
80 unsigned char *bp;
81
82 /*
83 * BSAFE is peculiar here. When IT DER-encodes public keys, it often generates
84 * a publicExponent whose leading bit (m.s. bit in the first byte) is 1. It
85 * reads these fine, of course. But when it DER-encodes the same value in the
86 * private key, it hews to DER rules and prepends a leading zero. If WE
87 * generate a private key with a field with a leading bit set, without the
88 * (technically) required leading zero, BSAFE pukes....but only when parsing
89 * private keys, not public keys. Same field (public exponent), different
90 * requirements for public and private keys. So we're cautious and prepend
91 * a zero if the leading field is one.
92 *
93 * This assumes of course that ALL numbers we're dealing with are positive....
94 */
95 buf = (unsigned char *)Malloc(numBytes + 1); // extra for possible prepend
96 if(buf == NULL) {
97 throw openSslException(CSSMERR_CSP_MEMORY_ERROR);
98 }
99 BN_bn2bin(bn, buf + 1);
100 if(buf[1] & 0x80) {
101 /* pedantic DER rules for BSAFE - make sure first byte is zero */
102 buf[0] = 0;
103 bp = buf;
104 numBytes++;
105 }
106 else {
107 /* use what BN_bn2bin gave us */
108 bp = buf+1;
109 }
110 snaccInt.ReSet((char *)bp, numBytes);
111 Free(buf);
112 }
113
114 /* estimate size of encoded BigIntegerStr */
115 unsigned sizeofBigInt(
116 BigIntegerStr &bigInt)
117 {
118 return bigInt.Len() + 4;
119 }
120
121 /* set up a encoded NULL for AlgorithmIdentifier.parameters, required for RSA */
122 static void nullAlgParams(
123 AlgorithmIdentifier &snaccAlgId)
124 {
125 snaccAlgId.parameters = new AsnAny;
126 char encodedNull[2] = {NULLTYPE_TAG_CODE, 0};
127 CSM_Buffer *cbuf = new CSM_Buffer(encodedNull, 2);
128 snaccAlgId.parameters->value = cbuf;
129 }
130
131 /*
132 * int --> BigIntegerStr
133 */
134 void snaccIntToBigIntegerStr(
135 int i,
136 BigIntegerStr &bigInt)
137 {
138 char c[4];
139 int dex;
140 int numChars;
141
142 if(i >= 0x1000000) {
143 numChars = 4;
144 }
145 else if(i > 0x10000) {
146 numChars = 3;
147 }
148 else if(i > 0x100) {
149 numChars = 2;
150 }
151 else {
152 numChars = 1;
153 }
154 /* i ==> DER */
155 for(dex=numChars-1; dex>=0; dex--) {
156 c[dex] = i & 0xff;
157 i >>= 8;
158 }
159
160 bigInt.ReSet(c, 4);
161 }
162
163 /*
164 * Replacements for d2i_RSAPublicKey, etc.
165 */
166 CSSM_RETURN RSAPublicKeyDecode(
167 RSA *openKey,
168 void *p,
169 size_t length)
170 {
171 RSAPublicKey snaccPubKey;
172
173 CssmData cData(p, length);
174 try {
175 SC_decodeAsnObj(cData, snaccPubKey);
176 }
177 catch(...) {
178 return CSSMERR_CSP_INVALID_KEY;
179 }
180 try {
181 openKey->n = bigIntStrToBn(snaccPubKey.modulus);
182 openKey->e = bigIntStrToBn(snaccPubKey.publicExponent);
183 }
184 catch(...) {
185 /* FIXME - bad sig? memory? */
186 return CSSMERR_CSP_MEMORY_ERROR;
187 }
188 return 0;
189 }
190
191 CSSM_RETURN RSAPublicKeyEncode(
192 RSA *openKey,
193 CssmOwnedData &encodedKey)
194 {
195 /* First convert into a snacc-style public key */
196 RSAPublicKey snaccPubKey;
197
198 try {
199 bnToBigIntStr(openKey->n, snaccPubKey.modulus);
200 bnToBigIntStr(openKey->e, snaccPubKey.publicExponent);
201 }
202 catch(...) {
203 /* ? */
204 return CSSMERR_CSP_MEMORY_ERROR;
205 }
206
207 /* conservative guess for max size of encoded key */
208 unsigned maxSize = sizeofBigInt(snaccPubKey.modulus) +
209 sizeofBigInt(snaccPubKey.publicExponent) +
210 20;
211
212 /* DER encode */
213 try {
214 SC_encodeAsnObj(snaccPubKey, encodedKey, maxSize);
215 }
216 catch(...) {
217 /* ? */
218 return CSSMERR_CSP_MEMORY_ERROR;
219 }
220 return 0;
221 }
222
223 CSSM_RETURN RSAPrivateKeyDecode(
224 RSA *openKey,
225 void *p,
226 size_t length)
227 {
228 PrivateKeyInfo snaccPrivKeyInfo;
229 CssmData cData(p, length);
230 try {
231 SC_decodeAsnObj(cData, snaccPrivKeyInfo);
232 }
233 catch(...) {
234 return CSSMERR_CSP_INVALID_KEY;
235 }
236
237 /* verify alg identifier */
238 if(snaccPrivKeyInfo.privateKeyAlgorithm == NULL) {
239 sslSnaccDebug("RSAPrivateKeyDecode: no privateKeyAlgorithm");
240 return CSSMERR_CSP_INVALID_KEY;
241 }
242 if(snaccPrivKeyInfo.privateKeyAlgorithm->algorithm != rsaEncryption) {
243 sslSnaccDebug("RSAPrivateKeyDecode: bad privateKeyAlgorithm");
244 return CSSMERR_CSP_ALGID_MISMATCH;
245 }
246
247 /*
248 * snaccPrivKeyInfo.privateKey is an octet string which needs
249 * subsequent decoding
250 */
251 char *rawOcts = snaccPrivKeyInfo.privateKey;
252 unsigned numBytes = snaccPrivKeyInfo.privateKey.Len();
253 RSAPrivateKey snaccPrivKey;
254 CssmData cData2(rawOcts, numBytes);
255 try {
256 SC_decodeAsnObj(cData2, snaccPrivKey);
257 }
258 catch(...) {
259 sslSnaccDebug("RSAPrivateKeyDecode: bad snaccPrivKeyInfo.privateKey");
260 return CSSMERR_CSP_INVALID_KEY;
261 }
262
263 /* convert snaccPrivKey fields to RSA key fields */
264 try {
265 openKey->version = snaccPrivKey.version;
266 openKey->n = bigIntStrToBn(snaccPrivKey.modulus);
267 openKey->e = bigIntStrToBn(snaccPrivKey.publicExponent);
268 openKey->d = bigIntStrToBn(snaccPrivKey.privateExponent);
269 openKey->p = bigIntStrToBn(snaccPrivKey.prime1);
270 openKey->q = bigIntStrToBn(snaccPrivKey.prime2);
271 openKey->dmp1 = bigIntStrToBn(snaccPrivKey.exponent1);
272 openKey->dmq1 = bigIntStrToBn(snaccPrivKey.exponent2);
273 openKey->iqmp = bigIntStrToBn(snaccPrivKey.coefficient);
274 }
275 catch(...) {
276 /* FIXME - bad sig? memory? */
277 return CSSMERR_CSP_MEMORY_ERROR;
278 }
279 return 0;
280 }
281
282 CSSM_RETURN RSAPrivateKeyEncode(
283 RSA *openKey,
284 CssmOwnedData &encodedKey)
285 {
286 /* First convert into a snacc-style private key */
287 RSAPrivateKey snaccPrivKey;
288
289 try {
290 snaccPrivKey.version = openKey->version;
291 bnToBigIntStr(openKey->n, snaccPrivKey.modulus);
292 bnToBigIntStr(openKey->e, snaccPrivKey.publicExponent);
293 bnToBigIntStr(openKey->d, snaccPrivKey.privateExponent);
294 bnToBigIntStr(openKey->p, snaccPrivKey.prime1);
295 bnToBigIntStr(openKey->q, snaccPrivKey.prime2);
296 bnToBigIntStr(openKey->dmp1, snaccPrivKey.exponent1);
297 bnToBigIntStr(openKey->dmq1, snaccPrivKey.exponent2);
298 bnToBigIntStr(openKey->iqmp, snaccPrivKey.coefficient);
299 }
300 catch(...) {
301 /* ? */
302 return CSSMERR_CSP_MEMORY_ERROR;
303 }
304
305 /* conservative guess for max size of encoded key */
306 unsigned maxSize = sizeofBigInt(snaccPrivKey.modulus) +
307 sizeofBigInt(snaccPrivKey.publicExponent) +
308 sizeofBigInt(snaccPrivKey.privateExponent) +
309 sizeofBigInt(snaccPrivKey.prime1) +
310 sizeofBigInt(snaccPrivKey.prime2) +
311 sizeofBigInt(snaccPrivKey.exponent1) +
312 sizeofBigInt(snaccPrivKey.exponent2) +
313 sizeofBigInt(snaccPrivKey.coefficient) +
314 64; // includes the to-be-generated algId
315
316 /* DER encode */
317 try {
318 SC_encodeAsnObj(snaccPrivKey, encodedKey, maxSize);
319 }
320 catch(...) {
321 /* ? */
322 return CSSMERR_CSP_MEMORY_ERROR;
323 }
324
325 /* that encoding is the privateKey field of a PrivateKeyInfo */
326 PrivateKeyInfo snaccPrivKeyInfo;
327 snaccPrivKeyInfo.version = 0; /* I think.... */
328 snaccPrivKeyInfo.privateKeyAlgorithm = new AlgorithmIdentifier;
329 snaccPrivKeyInfo.privateKeyAlgorithm->algorithm = rsaEncryption;
330 nullAlgParams(*snaccPrivKeyInfo.privateKeyAlgorithm);
331 snaccPrivKeyInfo.privateKey.Set((char *)encodedKey.data(), encodedKey.length());
332
333 /* now encode the privateKeyInfo */
334 encodedKey.reset();
335 try {
336 SC_encodeAsnObj(snaccPrivKeyInfo, encodedKey, maxSize);
337 }
338 catch(...) {
339 /* ? */
340 return CSSMERR_CSP_MEMORY_ERROR;
341 }
342 return 0;
343 }
344
345 /*
346 * Given a message digest and associated algorithm, cook up a PKCS1-style
347 * DigestInfo and return its DER encoding. This is a necessary step for
348 * RSA signature (both generating and verifying) - the output of this
349 * routine is what gets encrypted during signing, and what is expected when
350 * verifying (i.e., decrypting the signature).
351 *
352 * A good guess for the length of the output digestInfo is the size of the
353 * key being used to sign/verify. The digest can never be larger than that.
354 */
355 CSSM_RETURN generateDigestInfo(
356 const void *msgDigest,
357 size_t digestLen,
358 CSSM_ALGORITHMS digestAlg, // CSSM_ALGID_SHA1, etc.
359 CssmOwnedData &encodedInfo,
360 size_t maxEncodedSize)
361 {
362 if(digestAlg == CSSM_ALGID_NONE) {
363 /* special case, no encode, just copy */
364 encodedInfo.copy(msgDigest, digestLen);
365 return 0;
366 }
367
368 DigestInfo info;
369 info.digest.Set((char *)msgDigest, digestLen);
370 info.digestAlgorithm = new DigestAlgorithmIdentifier;
371
372 switch(digestAlg) {
373 case CSSM_ALGID_MD5:
374 info.digestAlgorithm->algorithm = md5;
375 break;
376 case CSSM_ALGID_MD2:
377 info.digestAlgorithm->algorithm = md2;
378 break;
379 case CSSM_ALGID_SHA1:
380 info.digestAlgorithm->algorithm = sha_1;
381 break;
382 default:
383 return CSSMERR_CSP_INVALID_ALGORITHM;
384 }
385 nullAlgParams(*info.digestAlgorithm);
386 try {
387 SC_encodeAsnObj(info, encodedInfo, maxEncodedSize);
388 }
389 catch(...) {
390 /* FIXME - bad sig? memory? */
391 return CSSMERR_CSP_MEMORY_ERROR;
392 }
393 return 0;
394 }
395
396 unsigned sizeofAsnBits(
397 AsnBits &bits)
398 {
399 return (bits.BitLen() * 8) + 4;
400 }
401
402 unsigned sizeofAsnOcts(
403 AsnOcts &octs)
404 {
405 return octs.Len() + 4;
406 }
407
408
409 /***
410 *** DSA
411 ***/
412
413 /* SNACC DSAAlgorithmId <--> DSA->{p,g,q} */
414 static DSAAlgorithmId *dsaToSnaccAlgId(
415 const DSA *openKey)
416 {
417 try {
418 DSAAlgorithmId *algId = new DSAAlgorithmId;
419
420 algId->algorithm = dsa_bsafe;
421 algId->params = new DSABsafeParams;
422 algId->params->keySizeInBits = BN_num_bits(openKey->p);
423 bnToBigIntStr(openKey->p, algId->params->p);
424 bnToBigIntStr(openKey->q, algId->params->q);
425 bnToBigIntStr(openKey->g, algId->params->g);
426 return algId;
427 }
428 catch(...) {
429 return NULL;
430 }
431 }
432
433 static CSSM_RETURN snaccAlgIdToDsa(
434 DSAAlgorithmId &algId,
435 DSA *openKey)
436 {
437 if(algId.algorithm != dsa_bsafe) {
438 sslSnaccDebug("snaccAlgIdToDsa: bad algorithm");
439 return CSSMERR_CSP_ALGID_MISMATCH;
440 }
441 if(algId.params == NULL) {
442 sslSnaccDebug("snaccAlgIdToDsa: bad params");
443 return CSSMERR_CSP_INVALID_KEY;
444 }
445 openKey->p = bigIntStrToBn(algId.params->p);
446 openKey->q = bigIntStrToBn(algId.params->q);
447 openKey->g = bigIntStrToBn(algId.params->g);
448 return 0;
449 }
450
451 static unsigned sizeOfDsaAlg(
452 const DSAAlgorithmId &algId)
453 {
454 return sizeofBigInt(algId.params->p) +
455 sizeofBigInt(algId.params->g) +
456 sizeofBigInt(algId.params->q) +
457 30;
458 }
459
460 CSSM_RETURN DSAPublicKeyDecode(
461 DSA *openKey,
462 unsigned char *p,
463 unsigned length)
464 {
465 DSAPublicKey snaccPubKey;
466 CSSM_RETURN rtn;
467
468 CssmData cData(p, length);
469 try {
470 SC_decodeAsnObj(cData, snaccPubKey);
471 rtn = snaccAlgIdToDsa(*snaccPubKey.dsaAlg, openKey);
472 if(rtn) {
473 return rtn;
474 }
475
476 /* inside of snaccPubKey.publicKey is the DER-encoding of a BigIntegerStr */
477 char *keyOcts = (char *)snaccPubKey.publicKey.BitOcts();
478 CssmData kData(keyOcts, (snaccPubKey.publicKey.BitLen() + 7) / 8);
479 BigIntegerStr pubKeyOcts;
480 SC_decodeAsnObj(kData, pubKeyOcts);
481 openKey->pub_key = bigIntStrToBn(pubKeyOcts);
482
483 if(openKey->pub_key == NULL) {
484 return CSSMERR_CSP_INVALID_KEY;
485 }
486 return 0;
487 }
488 catch(...) {
489 return CSSMERR_CSP_INVALID_KEY;
490 }
491 }
492
493 CSSM_RETURN DSAPublicKeyEncode(
494 DSA *openKey,
495 CssmOwnedData &encodedKey)
496 {
497 try {
498 /* First convert into a snacc-style public key */
499 DSAPublicKey snaccPubKey;
500
501 snaccPubKey.dsaAlg = dsaToSnaccAlgId(openKey);
502 if(snaccPubKey.dsaAlg == NULL) {
503 return CSSMERR_CSP_MEMORY_ERROR;
504 }
505
506 /*
507 * publicKey is the DER-encoding of a BigIntegerStr wrapped in
508 * an AsnBits
509 */
510 BigIntegerStr pubKeyInt;
511 bnToBigIntStr(openKey->pub_key, pubKeyInt);
512 unsigned maxSize = sizeofBigInt(pubKeyInt);
513 SC_encodeAsnObj(pubKeyInt, encodedKey, maxSize);
514
515 /* that encoding goes into DSAPublicKey.publicKey */
516 snaccPubKey.publicKey.Set((char *)encodedKey.data(), encodedKey.length() * 8);
517
518 /* conservative guess for max size of encoded key */
519 maxSize = sizeOfDsaAlg(*snaccPubKey.dsaAlg) +
520 sizeofAsnBits(snaccPubKey.publicKey) +
521 20;
522
523 /* DER encode */
524 encodedKey.reset();
525 SC_encodeAsnObj(snaccPubKey, encodedKey, maxSize);
526 return 0;
527 }
528 catch(...) {
529 /* ? */
530 return CSSMERR_CSP_MEMORY_ERROR;
531 }
532 }
533
534 CSSM_RETURN DSAPrivateKeyDecode(
535 DSA *openKey,
536 unsigned char *p,
537 unsigned length)
538 {
539 DSAPrivateKey snaccPrivKey;
540 int rtn;
541
542 CssmData cData(p, length);
543 try {
544 SC_decodeAsnObj(cData, snaccPrivKey);
545 openKey->version = snaccPrivKey.version;
546
547 rtn = snaccAlgIdToDsa(*snaccPrivKey.dsaAlg, openKey);
548 if(rtn) {
549 return rtn;
550 }
551
552 /* snaccPrivKey.privateKey is the DER-encoding of a DSAPrivateKeyOcts... */
553 char *keyOcts = snaccPrivKey.privateKey;
554 CssmData kData(keyOcts, snaccPrivKey.privateKey.Len());
555 DSAPrivateKeyOcts privKeyOcts;
556 SC_decodeAsnObj(kData, privKeyOcts);
557
558 openKey->priv_key = bigIntStrToBn(privKeyOcts.privateKey);
559 if(openKey->priv_key == NULL) {
560 return CSSMERR_CSP_INVALID_KEY;
561 }
562 return 0;
563 }
564 catch(...) {
565 return CSSMERR_CSP_INVALID_KEY;
566 }
567 }
568
569 CSSM_RETURN DSAPrivateKeyEncode(
570 DSA *openKey,
571 CssmOwnedData &encodedKey)
572 {
573 try {
574 /* First convert into a snacc-style private key */
575 DSAPrivateKey snaccPrivKey;
576
577 snaccPrivKey.version = openKey->version;
578 snaccPrivKey.dsaAlg = dsaToSnaccAlgId(openKey);
579 if(snaccPrivKey.dsaAlg == NULL) {
580 return CSSMERR_CSP_MEMORY_ERROR;
581 }
582
583 /* DSAPrivateKey.privateKey is the DER-encoding of one of these... */
584 DSAPrivateKeyOcts privKeyOcts;
585 bnToBigIntStr(openKey->priv_key, privKeyOcts.privateKey);
586
587 /* conservative guess for max size of encoded privKey bits */
588 unsigned maxSize = sizeofBigInt(privKeyOcts.privateKey) +
589 10; // includes the to-be-generated algId
590
591 /* DER encode */
592 SC_encodeAsnObj(privKeyOcts, encodedKey, maxSize);
593
594 /* that encoding goes into DSAPrivateKey.privateKey */
595 snaccPrivKey.privateKey.Set((char *)encodedKey.data(), encodedKey.length());
596
597 /* conservative guess for max size of the whole thing */
598 maxSize = maxSize + // what we just did
599 sizeOfDsaAlg(*snaccPrivKey.dsaAlg) +
600 40;
601
602 /* DER encode */
603 encodedKey.reset();
604 SC_encodeAsnObj(snaccPrivKey, encodedKey, maxSize);
605 return 0;
606 }
607 catch(...) {
608 /* ? */
609 return CSSMERR_CSP_MEMORY_ERROR;
610 }
611 }
612
613 CSSM_RETURN DSASigEncode(
614 DSA_SIG *openSig,
615 CssmOwnedData &encodedSig)
616 {
617 /* First convert into a snacc-style sig */
618 DSASignature snaccSig;
619
620 try {
621 bnToBigIntStr(openSig->r, snaccSig.r);
622 bnToBigIntStr(openSig->s, snaccSig.s);
623 }
624 catch(...) {
625 /* ? */
626 return CSSMERR_CSP_MEMORY_ERROR;
627 }
628
629 /* conservative guess for max size of encoded key */
630 unsigned maxSize = sizeofBigInt(snaccSig.r) +
631 sizeofBigInt(snaccSig.s) +
632 10;
633
634 /* DER encode */
635 try {
636 SC_encodeAsnObj(snaccSig, encodedSig, maxSize);
637 }
638 catch(...) {
639 /* ? */
640 return CSSMERR_CSP_MEMORY_ERROR;
641 }
642 return 0;
643 }
644
645 CSSM_RETURN DSASigDecode(
646 DSA_SIG *openSig,
647 const void *p,
648 unsigned length)
649 {
650 DSASignature snaccSig;
651
652 CssmData cData((char *)p, length);
653 try {
654 SC_decodeAsnObj(cData, snaccSig);
655 }
656 catch(...) {
657 return CSSMERR_CSP_INVALID_SIGNATURE;
658 }
659 try {
660 openSig->r = bigIntStrToBn(snaccSig.r);
661 openSig->s = bigIntStrToBn(snaccSig.s);
662 }
663 catch(...) {
664 /* FIXME - bad sig? memory? */
665 return CSSMERR_CSP_MEMORY_ERROR;
666 }
667 return 0;
668 }
669
670 CSSM_RETURN DHPrivateKeyDecode(
671 DH *openKey,
672 unsigned char *p,
673 unsigned length)
674 {
675 DHPrivateKey snaccPrivKey;
676 CssmData cData(p, length);
677 try {
678 SC_decodeAsnObj(cData, snaccPrivKey);
679 }
680 catch(...) {
681 return CSSMERR_CSP_INVALID_KEY;
682 }
683
684 /* verify alg identifier */
685 if(snaccPrivKey.dHOid != dhKeyAgreement) {
686 sslSnaccDebug("DHPrivateKeyDecode: bad privateKeyAlgorithm");
687 return CSSMERR_CSP_ALGID_MISMATCH;
688 }
689
690 DHParameter *params = snaccPrivKey.params;
691 if(params == NULL) {
692 /* not optional */
693 sslSnaccDebug("DHPrivateKeyDecode: missing key params");
694 return CSSMERR_CSP_INVALID_KEY;
695 }
696
697 /* convert snaccPrivKey fields to DH key fields */
698 try {
699 openKey->priv_key = bigIntStrToBn(snaccPrivKey.secretPart);
700 openKey->p = bigIntStrToBn(params->prime);
701 openKey->g = bigIntStrToBn(params->base);
702 /* TBD - ignore privateValueLength for now */
703 }
704 catch(...) {
705 /* FIXME - bad sig? memory? */
706 return CSSMERR_CSP_MEMORY_ERROR;
707 }
708 return 0;
709 }
710
711 CSSM_RETURN DHPrivateKeyEncode(
712 DH *openKey,
713 CssmOwnedData &encodedKey)
714 {
715 /* First convert into a snacc-style private key */
716 DHPrivateKey snaccPrivKey;
717 snaccPrivKey.params = new DHParameter;
718 DHParameter *params = snaccPrivKey.params;
719
720 try {
721 snaccPrivKey.dHOid.Set(dhKeyAgreement_arc);
722 bnToBigIntStr(openKey->priv_key, snaccPrivKey.secretPart);
723 bnToBigIntStr(openKey->p, params->prime);
724 bnToBigIntStr(openKey->g, params->base);
725 if(openKey->length) {
726 /* actually currently not supported */
727 params->privateValueLength = new BigIntegerStr();
728 snaccIntToBigIntegerStr(openKey->length, *params->privateValueLength);
729 }
730 }
731 catch(...) {
732 /* ? */
733 return CSSMERR_CSP_MEMORY_ERROR;
734 }
735
736 /* conservative guess for max size of encoded key */
737 unsigned maxSize = sizeofBigInt(snaccPrivKey.secretPart) +
738 sizeofBigInt(params->prime) +
739 sizeofBigInt(params->base) +
740 60; // includes dHOid, tags, lenghts
741 if(openKey->length) {
742 maxSize += sizeofBigInt(*params->privateValueLength);
743 }
744
745 /* DER encode */
746 try {
747 SC_encodeAsnObj(snaccPrivKey, encodedKey, maxSize);
748 }
749 catch(...) {
750 /* ? */
751 return CSSMERR_CSP_MEMORY_ERROR;
752 }
753 return 0;
754 }
755