]> git.saurik.com Git - apple/security.git/blob - AppleCSP/open_ssl/opensslUtils/openRsaSnacc.cpp
Security-29.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 /*
133 * Replacements for d2i_RSAPublicKey, etc.
134 */
135 CSSM_RETURN RSAPublicKeyDecode(
136 RSA *openKey,
137 void *p,
138 size_t length)
139 {
140 RSAPublicKey snaccPubKey;
141
142 CssmData cData(p, length);
143 try {
144 SC_decodeAsnObj(cData, snaccPubKey);
145 }
146 catch(...) {
147 return CSSMERR_CSP_INVALID_KEY;
148 }
149 try {
150 openKey->n = bigIntStrToBn(snaccPubKey.modulus);
151 openKey->e = bigIntStrToBn(snaccPubKey.publicExponent);
152 }
153 catch(...) {
154 /* FIXME - bad sig? memory? */
155 return CSSMERR_CSP_MEMORY_ERROR;
156 }
157 return 0;
158 }
159
160 CSSM_RETURN RSAPublicKeyEncode(
161 RSA *openKey,
162 CssmOwnedData &encodedKey)
163 {
164 /* First convert into a snacc-style public key */
165 RSAPublicKey snaccPubKey;
166
167 try {
168 bnToBigIntStr(openKey->n, snaccPubKey.modulus);
169 bnToBigIntStr(openKey->e, snaccPubKey.publicExponent);
170 }
171 catch(...) {
172 /* ? */
173 return CSSMERR_CSP_MEMORY_ERROR;
174 }
175
176 /* conservative guess for max size of encoded key */
177 unsigned maxSize = sizeofBigInt(snaccPubKey.modulus) +
178 sizeofBigInt(snaccPubKey.publicExponent) +
179 20;
180
181 /* DER encode */
182 try {
183 SC_encodeAsnObj(snaccPubKey, encodedKey, maxSize);
184 }
185 catch(...) {
186 /* ? */
187 return CSSMERR_CSP_MEMORY_ERROR;
188 }
189 return 0;
190 }
191
192 CSSM_RETURN RSAPrivateKeyDecode(
193 RSA *openKey,
194 void *p,
195 size_t length)
196 {
197 PrivateKeyInfo snaccPrivKeyInfo;
198 CssmData cData(p, length);
199 try {
200 SC_decodeAsnObj(cData, snaccPrivKeyInfo);
201 }
202 catch(...) {
203 return CSSMERR_CSP_INVALID_KEY;
204 }
205
206 /* verify alg identifier */
207 if(snaccPrivKeyInfo.privateKeyAlgorithm == NULL) {
208 sslSnaccDebug("RSAPrivateKeyDecode: no privateKeyAlgorithm");
209 return CSSMERR_CSP_INVALID_KEY;
210 }
211 if(snaccPrivKeyInfo.privateKeyAlgorithm->algorithm != rsaEncryption) {
212 sslSnaccDebug("RSAPrivateKeyDecode: bad privateKeyAlgorithm");
213 return CSSMERR_CSP_ALGID_MISMATCH;
214 }
215
216 /*
217 * snaccPrivKeyInfo.privateKey is an octet string which needs
218 * subsequent decoding
219 */
220 char *rawOcts = snaccPrivKeyInfo.privateKey;
221 unsigned numBytes = snaccPrivKeyInfo.privateKey.Len();
222 RSAPrivateKey snaccPrivKey;
223 CssmData cData2(rawOcts, numBytes);
224 try {
225 SC_decodeAsnObj(cData2, snaccPrivKey);
226 }
227 catch(...) {
228 sslSnaccDebug("RSAPrivateKeyDecode: bad snaccPrivKeyInfo.privateKey");
229 return CSSMERR_CSP_INVALID_KEY;
230 }
231
232 /* convert snaccPrivKey fields to RSA key fields */
233 try {
234 openKey->version = snaccPrivKey.version;
235 openKey->n = bigIntStrToBn(snaccPrivKey.modulus);
236 openKey->e = bigIntStrToBn(snaccPrivKey.publicExponent);
237 openKey->d = bigIntStrToBn(snaccPrivKey.privateExponent);
238 openKey->p = bigIntStrToBn(snaccPrivKey.prime1);
239 openKey->q = bigIntStrToBn(snaccPrivKey.prime2);
240 openKey->dmp1 = bigIntStrToBn(snaccPrivKey.exponent1);
241 openKey->dmq1 = bigIntStrToBn(snaccPrivKey.exponent2);
242 openKey->iqmp = bigIntStrToBn(snaccPrivKey.coefficient);
243 }
244 catch(...) {
245 /* FIXME - bad sig? memory? */
246 return CSSMERR_CSP_MEMORY_ERROR;
247 }
248 return 0;
249 }
250
251 CSSM_RETURN RSAPrivateKeyEncode(
252 RSA *openKey,
253 CssmOwnedData &encodedKey)
254 {
255 /* First convert into a snacc-style private key */
256 RSAPrivateKey snaccPrivKey;
257
258 try {
259 snaccPrivKey.version = openKey->version;
260 bnToBigIntStr(openKey->n, snaccPrivKey.modulus);
261 bnToBigIntStr(openKey->e, snaccPrivKey.publicExponent);
262 bnToBigIntStr(openKey->d, snaccPrivKey.privateExponent);
263 bnToBigIntStr(openKey->p, snaccPrivKey.prime1);
264 bnToBigIntStr(openKey->q, snaccPrivKey.prime2);
265 bnToBigIntStr(openKey->dmp1, snaccPrivKey.exponent1);
266 bnToBigIntStr(openKey->dmq1, snaccPrivKey.exponent2);
267 bnToBigIntStr(openKey->iqmp, snaccPrivKey.coefficient);
268 }
269 catch(...) {
270 /* ? */
271 return CSSMERR_CSP_MEMORY_ERROR;
272 }
273
274 /* conservative guess for max size of encoded key */
275 unsigned maxSize = sizeofBigInt(snaccPrivKey.modulus) +
276 sizeofBigInt(snaccPrivKey.publicExponent) +
277 sizeofBigInt(snaccPrivKey.privateExponent) +
278 sizeofBigInt(snaccPrivKey.prime1) +
279 sizeofBigInt(snaccPrivKey.prime2) +
280 sizeofBigInt(snaccPrivKey.exponent1) +
281 sizeofBigInt(snaccPrivKey.exponent2) +
282 sizeofBigInt(snaccPrivKey.coefficient) +
283 64; // includes the to-be-generated algId
284
285 /* DER encode */
286 try {
287 SC_encodeAsnObj(snaccPrivKey, encodedKey, maxSize);
288 }
289 catch(...) {
290 /* ? */
291 return CSSMERR_CSP_MEMORY_ERROR;
292 }
293
294 /* that encoding is the privateKey field of a PrivateKeyInfo */
295 PrivateKeyInfo snaccPrivKeyInfo;
296 snaccPrivKeyInfo.version = 0; /* I think.... */
297 snaccPrivKeyInfo.privateKeyAlgorithm = new AlgorithmIdentifier;
298 snaccPrivKeyInfo.privateKeyAlgorithm->algorithm = rsaEncryption;
299 nullAlgParams(*snaccPrivKeyInfo.privateKeyAlgorithm);
300 snaccPrivKeyInfo.privateKey.Set((char *)encodedKey.data(), encodedKey.length());
301
302 /* now encode the privateKeyInfo */
303 encodedKey.reset();
304 try {
305 SC_encodeAsnObj(snaccPrivKeyInfo, encodedKey, maxSize);
306 }
307 catch(...) {
308 /* ? */
309 return CSSMERR_CSP_MEMORY_ERROR;
310 }
311 return 0;
312 }
313
314 /*
315 * Given a message digest and associated algorithm, cook up a PKCS1-style
316 * DigestInfo and return its DER encoding. This is a necessary step for
317 * RSA signature (both generating and verifying) - the output of this
318 * routine is what gets encrypted during signing, and what is expected when
319 * verifying (i.e., decrypting the signature).
320 *
321 * A good guess for the length of the output digestInfo is the size of the
322 * key being used to sign/verify. The digest can never be larger than that.
323 */
324 CSSM_RETURN generateDigestInfo(
325 const void *msgDigest,
326 size_t digestLen,
327 CSSM_ALGORITHMS digestAlg, // CSSM_ALGID_SHA1, etc.
328 CssmOwnedData &encodedInfo,
329 size_t maxEncodedSize)
330 {
331 if(digestAlg == CSSM_ALGID_NONE) {
332 /* special case, no encode, just copy */
333 encodedInfo.copy(msgDigest, digestLen);
334 return 0;
335 }
336
337 DigestInfo info;
338 info.digest.Set((char *)msgDigest, digestLen);
339 info.digestAlgorithm = new DigestAlgorithmIdentifier;
340
341 switch(digestAlg) {
342 case CSSM_ALGID_MD5:
343 info.digestAlgorithm->algorithm = md5;
344 break;
345 case CSSM_ALGID_MD2:
346 info.digestAlgorithm->algorithm = md2;
347 break;
348 case CSSM_ALGID_SHA1:
349 info.digestAlgorithm->algorithm = sha_1;
350 break;
351 default:
352 return CSSMERR_CSP_INVALID_ALGORITHM;
353 }
354 nullAlgParams(*info.digestAlgorithm);
355 try {
356 SC_encodeAsnObj(info, encodedInfo, maxEncodedSize);
357 }
358 catch(...) {
359 /* FIXME - bad sig? memory? */
360 return CSSMERR_CSP_MEMORY_ERROR;
361 }
362 return 0;
363 }
364
365 unsigned sizeofAsnBits(
366 AsnBits &bits)
367 {
368 return (bits.BitLen() * 8) + 4;
369 }
370
371 unsigned sizeofAsnOcts(
372 AsnOcts &octs)
373 {
374 return octs.Len() + 4;
375 }
376
377
378 /***
379 *** DSA
380 ***/
381
382 /* SNACC DSAAlgorithmId <--> DSA->{p,g,q} */
383 static DSAAlgorithmId *dsaToSnaccAlgId(
384 const DSA *openKey)
385 {
386 try {
387 DSAAlgorithmId *algId = new DSAAlgorithmId;
388
389 algId->algorithm = dsa_bsafe;
390 algId->params = new DSABsafeParams;
391 algId->params->keySizeInBits = BN_num_bits(openKey->p);
392 bnToBigIntStr(openKey->p, algId->params->p);
393 bnToBigIntStr(openKey->q, algId->params->q);
394 bnToBigIntStr(openKey->g, algId->params->g);
395 return algId;
396 }
397 catch(...) {
398 return NULL;
399 }
400 }
401
402 static CSSM_RETURN snaccAlgIdToDsa(
403 DSAAlgorithmId &algId,
404 DSA *openKey)
405 {
406 if(algId.algorithm != dsa_bsafe) {
407 sslSnaccDebug("snaccAlgIdToDsa: bad algorithm");
408 return CSSMERR_CSP_ALGID_MISMATCH;
409 }
410 if(algId.params == NULL) {
411 sslSnaccDebug("snaccAlgIdToDsa: bad params");
412 return CSSMERR_CSP_INVALID_KEY;
413 }
414 openKey->p = bigIntStrToBn(algId.params->p);
415 openKey->q = bigIntStrToBn(algId.params->q);
416 openKey->g = bigIntStrToBn(algId.params->g);
417 return 0;
418 }
419
420 static unsigned sizeOfDsaAlg(
421 const DSAAlgorithmId &algId)
422 {
423 return sizeofBigInt(algId.params->p) +
424 sizeofBigInt(algId.params->g) +
425 sizeofBigInt(algId.params->q) +
426 30;
427 }
428
429 CSSM_RETURN DSAPublicKeyDecode(
430 DSA *openKey,
431 unsigned char *p,
432 unsigned length)
433 {
434 DSAPublicKey snaccPubKey;
435 CSSM_RETURN rtn;
436
437 CssmData cData(p, length);
438 try {
439 SC_decodeAsnObj(cData, snaccPubKey);
440 rtn = snaccAlgIdToDsa(*snaccPubKey.dsaAlg, openKey);
441 if(rtn) {
442 return rtn;
443 }
444
445 /* inside of snaccPubKey.publicKey is the DER-encoding of a BigIntegerStr */
446 char *keyOcts = (char *)snaccPubKey.publicKey.BitOcts();
447 CssmData kData(keyOcts, (snaccPubKey.publicKey.BitLen() + 7) / 8);
448 BigIntegerStr pubKeyOcts;
449 SC_decodeAsnObj(kData, pubKeyOcts);
450 openKey->pub_key = bigIntStrToBn(pubKeyOcts);
451
452 if(openKey->pub_key == NULL) {
453 return CSSMERR_CSP_INVALID_KEY;
454 }
455 return 0;
456 }
457 catch(...) {
458 return CSSMERR_CSP_INVALID_KEY;
459 }
460 }
461
462 CSSM_RETURN DSAPublicKeyEncode(
463 DSA *openKey,
464 CssmOwnedData &encodedKey)
465 {
466 try {
467 /* First convert into a snacc-style public key */
468 DSAPublicKey snaccPubKey;
469
470 snaccPubKey.dsaAlg = dsaToSnaccAlgId(openKey);
471 if(snaccPubKey.dsaAlg == NULL) {
472 return CSSMERR_CSP_MEMORY_ERROR;
473 }
474
475 /*
476 * publicKey is the DER-encoding of a BigIntegerStr wrapped in
477 * an AsnBits
478 */
479 BigIntegerStr pubKeyInt;
480 bnToBigIntStr(openKey->pub_key, pubKeyInt);
481 unsigned maxSize = sizeofBigInt(pubKeyInt);
482 SC_encodeAsnObj(pubKeyInt, encodedKey, maxSize);
483
484 /* that encoding goes into DSAPublicKey.publicKey */
485 snaccPubKey.publicKey.Set((char *)encodedKey.data(), encodedKey.length() * 8);
486
487 /* conservative guess for max size of encoded key */
488 maxSize = sizeOfDsaAlg(*snaccPubKey.dsaAlg) +
489 sizeofAsnBits(snaccPubKey.publicKey) +
490 20;
491
492 /* DER encode */
493 encodedKey.reset();
494 SC_encodeAsnObj(snaccPubKey, encodedKey, maxSize);
495 return 0;
496 }
497 catch(...) {
498 /* ? */
499 return CSSMERR_CSP_MEMORY_ERROR;
500 }
501 }
502
503 CSSM_RETURN DSAPrivateKeyDecode(
504 DSA *openKey,
505 unsigned char *p,
506 unsigned length)
507 {
508 DSAPrivateKey snaccPrivKey;
509 int rtn;
510
511 CssmData cData(p, length);
512 try {
513 SC_decodeAsnObj(cData, snaccPrivKey);
514 openKey->version = snaccPrivKey.version;
515
516 rtn = snaccAlgIdToDsa(*snaccPrivKey.dsaAlg, openKey);
517 if(rtn) {
518 return rtn;
519 }
520
521 /* snaccPrivKey.privateKey is the DER-encoding of a DSAPrivateKeyOcts... */
522 char *keyOcts = snaccPrivKey.privateKey;
523 CssmData kData(keyOcts, snaccPrivKey.privateKey.Len());
524 DSAPrivateKeyOcts privKeyOcts;
525 SC_decodeAsnObj(kData, privKeyOcts);
526
527 openKey->priv_key = bigIntStrToBn(privKeyOcts.privateKey);
528 if(openKey->priv_key == NULL) {
529 return CSSMERR_CSP_INVALID_KEY;
530 }
531 return 0;
532 }
533 catch(...) {
534 return CSSMERR_CSP_INVALID_KEY;
535 }
536 }
537
538 CSSM_RETURN DSAPrivateKeyEncode(
539 DSA *openKey,
540 CssmOwnedData &encodedKey)
541 {
542 try {
543 /* First convert into a snacc-style private key */
544 DSAPrivateKey snaccPrivKey;
545
546 snaccPrivKey.version = openKey->version;
547 snaccPrivKey.dsaAlg = dsaToSnaccAlgId(openKey);
548 if(snaccPrivKey.dsaAlg == NULL) {
549 return CSSMERR_CSP_MEMORY_ERROR;
550 }
551
552 /* DSAPrivateKey.privateKey is the DER-encoding of one of these... */
553 DSAPrivateKeyOcts privKeyOcts;
554 bnToBigIntStr(openKey->priv_key, privKeyOcts.privateKey);
555
556 /* conservative guess for max size of encoded privKey bits */
557 unsigned maxSize = sizeofBigInt(privKeyOcts.privateKey) +
558 10; // includes the to-be-generated algId
559
560 /* DER encode */
561 SC_encodeAsnObj(privKeyOcts, encodedKey, maxSize);
562
563 /* that encoding goes into DSAPrivateKey.privateKey */
564 snaccPrivKey.privateKey.Set((char *)encodedKey.data(), encodedKey.length());
565
566 /* conservative guess for max size of the whole thing */
567 maxSize = maxSize + // what we just did
568 sizeOfDsaAlg(*snaccPrivKey.dsaAlg) +
569 40;
570
571 /* DER encode */
572 encodedKey.reset();
573 SC_encodeAsnObj(snaccPrivKey, encodedKey, maxSize);
574 return 0;
575 }
576 catch(...) {
577 /* ? */
578 return CSSMERR_CSP_MEMORY_ERROR;
579 }
580 }
581
582 CSSM_RETURN DSASigEncode(
583 DSA_SIG *openSig,
584 CssmOwnedData &encodedSig)
585 {
586 /* First convert into a snacc-style sig */
587 DSASignature snaccSig;
588
589 try {
590 bnToBigIntStr(openSig->r, snaccSig.r);
591 bnToBigIntStr(openSig->s, snaccSig.s);
592 }
593 catch(...) {
594 /* ? */
595 return CSSMERR_CSP_MEMORY_ERROR;
596 }
597
598 /* conservative guess for max size of encoded key */
599 unsigned maxSize = sizeofBigInt(snaccSig.r) +
600 sizeofBigInt(snaccSig.s) +
601 10;
602
603 /* DER encode */
604 try {
605 SC_encodeAsnObj(snaccSig, encodedSig, maxSize);
606 }
607 catch(...) {
608 /* ? */
609 return CSSMERR_CSP_MEMORY_ERROR;
610 }
611 return 0;
612 }
613
614 CSSM_RETURN DSASigDecode(
615 DSA_SIG *openSig,
616 const void *p,
617 unsigned length)
618 {
619 DSASignature snaccSig;
620
621 CssmData cData((char *)p, length);
622 try {
623 SC_decodeAsnObj(cData, snaccSig);
624 }
625 catch(...) {
626 return CSSMERR_CSP_INVALID_SIGNATURE;
627 }
628 try {
629 openSig->r = bigIntStrToBn(snaccSig.r);
630 openSig->s = bigIntStrToBn(snaccSig.s);
631 }
632 catch(...) {
633 /* FIXME - bad sig? memory? */
634 return CSSMERR_CSP_MEMORY_ERROR;
635 }
636 return 0;
637 }