1/*
2 * bsafeUtils.c - common routines for CDSA/BSAFE compatibility testing
3 */
4
5
6#include <stdlib.h>
7#include <stdio.h>
8#include <time.h>
9#include <string.h>
10//#include <security_bsafe/bsafe.h>
11//#include <security_bsafe/aglobal.h>
12#include "bsafeUtils.h"
13#include <Security/cssmerr.h>
14#include "common.h"
15
16/*
17 * Convert between BSAFE ITEM and CSSM_DATA
18 */
19#if 0
20static inline void buItemToCssmData(
21	const ITEM 		*item,
22	CSSM_DATA_PTR	cdata)
23{
24	cdata->Data   = item->data;
25	cdata->Length = item->len;
26}
27
28static inline void buCssmDataToItem(
29	const CSSM_DATA		*cdata,
30	ITEM 				*item)
31{
32	item->data = cdata->Data;
33	item->len  = cdata->Length;
34}
35
36/*
37 * BSafe's Chooser table - all we'll ever need.
38 */
39/*static*/ B_ALGORITHM_METHOD *BSAFE_ALGORITHM_CHOOSER[] = {
40    // digests
41    &AM_SHA,
42    &AM_MD5,
43	&AM_MD2,
44
45    // organizational
46    &AM_CBC_ENCRYPT,
47    &AM_CBC_DECRYPT,
48    &AM_ECB_ENCRYPT,
49    &AM_ECB_DECRYPT,
50    &AM_OFB_ENCRYPT,
51    &AM_OFB_DECRYPT,
52
53    // DES & variants
54    &AM_DES_ENCRYPT,
55    &AM_DES_DECRYPT,
56    &AM_DESX_ENCRYPT,
57    &AM_DESX_DECRYPT,
58    &AM_DES_EDE_ENCRYPT,
59    &AM_DES_EDE_DECRYPT,
60
61    // RCn stuff
62    &AM_RC2_CBC_ENCRYPT,
63    &AM_RC2_CBC_DECRYPT,
64    &AM_RC2_ENCRYPT,
65    &AM_RC2_DECRYPT,
66    &AM_RC4_ENCRYPT,
67    &AM_RC4_DECRYPT,
68    &AM_RC5_ENCRYPT,
69    &AM_RC5_DECRYPT,
70    &AM_RC5_CBC_ENCRYPT,
71    &AM_RC5_CBC_DECRYPT,
72
73    // RSA
74    &AM_RSA_STRONG_KEY_GEN,
75    &AM_RSA_KEY_GEN,
76    &AM_RSA_CRT_ENCRYPT_BLIND,
77    &AM_RSA_CRT_DECRYPT_BLIND,
78    &AM_RSA_ENCRYPT,
79    &AM_RSA_DECRYPT,
80
81    // DSA
82    &AM_DSA_PARAM_GEN,
83    &AM_DSA_KEY_GEN,
84
85    // signatures
86    &AM_DSA_SIGN,
87    &AM_DSA_VERIFY,
88
89    // random number generation
90    &AM_MD5_RANDOM,
91    &AM_SHA_RANDOM,
92
93    // sentinel
94    (B_ALGORITHM_METHOD *)NULL_PTR
95};
96
97/*
98 * Convert a BSAFE return to a CSSM error and optionally print the error msg with
99 * the op in which the error occurred.
100 */
101static CSSM_RETURN buBsafeErrToCssm(
102	int brtn,
103	const char *op)
104{
105	const char *errStr = NULL;
106	CSSM_RETURN crtn;
107
108    switch (brtn) {
109		case 0:
110			return CSSM_OK;
111		case BE_ALLOC:
112			crtn = CSSMERR_CSSM_MEMORY_ERROR;
113			errStr = "BE_ALLOC";
114			break;
115		case BE_SIGNATURE:
116			crtn = CSSMERR_CSP_VERIFY_FAILED;
117			errStr = "BE_SIGNATURE";
118			break;
119		case BE_OUTPUT_LEN:
120			crtn = CSSMERR_CSP_OUTPUT_LENGTH_ERROR;
121			errStr = "BE_OUTPUT_LEN";
122			break;
123		case BE_INPUT_LEN:
124			crtn = CSSMERR_CSP_INPUT_LENGTH_ERROR;
125			errStr = "BE_INPUT_LEN";
126			break;
127		case BE_EXPONENT_EVEN:
128			crtn = CSSMERR_CSP_INVALID_KEY;
129			errStr = "BE_EXPONENT_EVEN";
130			break;
131		case BE_EXPONENT_LEN:
132			crtn = CSSMERR_CSP_INVALID_KEY;
133			errStr = "BE_EXPONENT_LEN";
134			break;
135		case BE_EXPONENT_ONE:
136			crtn = CSSMERR_CSP_INVALID_KEY;
137			errStr = "BE_EXPONENT_ONE";
138			break;
139		case BE_DATA:
140			crtn = CSSMERR_CSP_INVALID_DATA;
141			errStr = "BE_DATA";
142			break;
143		case BE_INPUT_DATA:
144			crtn = CSSMERR_CSP_INVALID_DATA;
145			errStr = "BE_INPUT_DATA";
146			break;
147		case BE_WRONG_KEY_INFO:
148			crtn = CSSMERR_CSP_INVALID_KEY;
149			errStr = "BE_WRONG_KEY_INFO";
150			break;
151        default:
152			//@@@ translate BSafe errors intelligently
153 			crtn = CSSM_ERRCODE_INTERNAL_ERROR;
154			errStr = "Other BSAFE error";
155			break;
156    }
157	if(op != NULL) {
158		printf("%s: BSAFE error %d (%s)\n", op, brtn, errStr);
159	}
160	return crtn;
161}
162
163/*
164 * Non-thread-safe global random B_ALGORITHM_OBJ and a reusable init for it.
165 */
166static B_ALGORITHM_OBJ 	bsafeRng = NULL;
167#define BSAFE_RANDSIZE	64
168
169static B_ALGORITHM_OBJ buGetRng()
170{
171	int brtn;
172	uint8 seed[BSAFE_RANDSIZE];
173
174	if(bsafeRng != NULL) {
175		return bsafeRng;
176	}
177	brtn = B_CreateAlgorithmObject(&bsafeRng);
178	if(brtn) {
179		buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject(&bsafeRng)");
180		return NULL;
181	}
182	brtn = B_SetAlgorithmInfo(bsafeRng, AI_X962Random_V0, NULL_PTR);
183	if(brtn) {
184		buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo(bsafeRng)");
185		return NULL;
186	}
187	brtn = B_RandomInit(bsafeRng, BSAFE_ALGORITHM_CHOOSER, NULL);
188 	if(brtn) {
189		buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo(bsafeRng)");
190		return NULL;
191	}
192	appGetRandomBytes(seed, BSAFE_RANDSIZE);
193	brtn = B_RandomUpdate(bsafeRng, seed, BSAFE_RANDSIZE, NULL);
194	if(brtn) {
195		buBsafeErrToCssm(brtn, "B_RandomUpdate");
196		return NULL;
197	}
198	return bsafeRng;
199}
200#endif
201
202/*
203 * Create a symmetric key.
204 */
205CSSM_RETURN  buGenSymKey(
206	uint32			keySizeInBits,
207	const CSSM_DATA	*keyData,
208	BU_KEY			*key)			// RETURNED
209{
210#if 0
211	int				brtn;
212	B_KEY_OBJ		bkey = NULL;
213	ITEM			item;
214	unsigned		keyBytes = (keySizeInBits + 7) / 8;
215
216	if(keyBytes > keyData->Length) {
217		/* note it's OK to give us too much key data */
218		printf("***buGenSymKey: Insufficient keyData\n");
219		return CSSM_ERRCODE_INTERNAL_ERROR;
220	}
221
222	/* create a BSAFE key */
223	brtn = B_CreateKeyObject(&bkey);
224	if(brtn) {
225		return buBsafeErrToCssm(brtn, "B_CreateKeyObject");
226	}
227
228	/* assign data to the key */
229	item.data = keyData->Data;
230	item.len = keyBytes;
231	brtn = B_SetKeyInfo(bkey, KI_Item, (POINTER)&item);
232	if(brtn) {
233		return buBsafeErrToCssm(brtn, "B_SetKeyInfo");
234	}
235	else {
236		*key = bkey;
237		return CSSM_OK;
238	}
239#endif
240    return 0;
241}
242
243/*
244 * Create asymmetric key pair.
245 * FIXME - additional params (e.g. DSA params, RSA exponent)?
246 */
247CSSM_RETURN buGenKeyPair(
248	uint32			keySizeInBits,
249	CSSM_ALGORITHMS	keyAlg,			// CSSM_ALGID_{RSA,DSA}
250	BU_KEY			*pubKey,		// RETURNED
251	BU_KEY			*privKey)		// RETURNED
252{
253#if 0 // NO MORE BSAFE
254	int						brtn;
255	B_KEY_OBJ				bPubkey = NULL;
256	B_KEY_OBJ				bPrivkey = NULL;
257	B_ALGORITHM_OBJ			keypairGen = NULL;
258	const char				*op = NULL;
259	A_RSA_KEY_GEN_PARAMS	params;
260	unsigned char 			exp[1] = { 3 };
261    B_ALGORITHM_OBJ 		genDsaAlg = NULL;
262    B_ALGORITHM_OBJ 		dsaResult = NULL;
263	B_DSA_PARAM_GEN_PARAMS 	dsaParams;
264	A_DSA_PARAMS 			*kParams = NULL;
265
266	/* create algorithm object */
267	brtn = B_CreateAlgorithmObject(&keypairGen);
268	if(brtn) {
269		return CSSMERR_CSSM_MEMORY_ERROR;
270	}
271
272	/* create two BSAFE keys */
273	brtn = B_CreateKeyObject(&bPubkey);
274	if(brtn) {
275		op ="B_CreateKeyObject";
276		goto abort;
277	}
278	brtn = B_CreateKeyObject(&bPrivkey);
279	if(brtn) {
280		op ="B_CreateKeyObject";
281		goto abort;
282	}
283	switch(keyAlg) {
284		case CSSM_ALGID_RSA:
285		{
286			/* set RSA-specific params */
287			params.modulusBits = keySizeInBits;
288			/* hack - parameterize? */
289			params.publicExponent.data = exp;
290			params.publicExponent.len = 1;
291			brtn = B_SetAlgorithmInfo(keypairGen, AI_RSAKeyGen,
292				(POINTER)&params);
293			if(brtn) {
294				op ="B_SetAlgorithmInfo(AI_RSAKeyGen)";
295			}
296			break;
297		}
298		case CSSM_ALGID_DSA:
299		{
300			/* jump through hoops generating parameters */
301			brtn = B_CreateAlgorithmObject(&genDsaAlg);
302			if(brtn) {
303				op ="B_CreateAlgorithmObject";
304				break;
305			}
306			dsaParams.primeBits = keySizeInBits;
307        	brtn = B_SetAlgorithmInfo(genDsaAlg, AI_DSAParamGen, (POINTER)&dsaParams);
308			if(brtn) {
309				op = "B_SetAlgorithmInfo(AI_DSAParamGen)";
310				break;
311			}
312			brtn = B_GenerateInit(genDsaAlg, BSAFE_ALGORITHM_CHOOSER, NULL);
313			if(brtn) {
314				op = "B_GenerateInit(AI_DSAParamGen)";
315				break;
316			}
317        	brtn = B_CreateAlgorithmObject(&dsaResult);
318			if(brtn) {
319				op = "B_CreateAlgorithmObject";
320				break;
321			}
322        	brtn = B_GenerateParameters(genDsaAlg, dsaResult, buGetRng(), NULL);
323			if(brtn) {
324				op = "B_GenerateParameters";
325				break;
326			}
327
328			/* dsaResult now has the parameters, which we must extract and then
329			 * apply to the keypairGen object. Cool, huh? */
330			brtn = B_GetAlgorithmInfo((POINTER *)&kParams, dsaResult, AI_DSAKeyGen);
331			if(brtn) {
332				op = "B_GetAlgorithmInfo(AI_DSAKeyGen)";
333				break;
334			}
335			brtn = B_SetAlgorithmInfo(keypairGen, AI_DSAKeyGen, (POINTER)kParams);
336			if(brtn) {
337				op ="B_SetAlgorithmInfo(AI_DSAKeyGen)";
338			}
339			break;
340		}
341		default:
342			printf("buGenKeyPair: algorithm not supported\n");
343			return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
344	}
345	if(brtn) {
346		goto abort;
347	}
348
349	/* keypairGen all set to go. */
350	brtn = B_GenerateInit(keypairGen,
351		BSAFE_ALGORITHM_CHOOSER,
352		(A_SURRENDER_CTX *)NULL);
353	if(brtn) {
354		op = "B_GenerateInit";
355		goto abort;
356	}
357	brtn = B_GenerateKeypair(keypairGen,
358		bPubkey,
359		bPrivkey,
360		buGetRng(),
361		NULL);
362	if(brtn) {
363		op = "B_GenerateInit";
364	}
365abort:
366	B_DestroyAlgorithmObject(&keypairGen);
367	B_DestroyAlgorithmObject(&genDsaAlg);
368	B_DestroyAlgorithmObject(&dsaResult);
369	if(brtn) {
370		B_DestroyKeyObject(&bPubkey);
371		B_DestroyKeyObject(&bPrivkey);
372		return buBsafeErrToCssm(brtn, op);
373	}
374	else {
375		*pubKey = bPubkey;
376		*privKey = bPrivkey;
377		return CSSM_OK;
378	}
379#endif
380	return CSSM_OK;
381}
382
383/*
384 * Free a key created in buGenSymKey or buGenKeyPair
385 */
386CSSM_RETURN buFreeKey(
387	BU_KEY			key)
388{
389#if 0 // NO MORE BSAFE
390	B_KEY_OBJ bkey = (B_KEY_OBJ)key;
391	B_DestroyKeyObject(&bkey);
392#endif
393	return CSSM_OK;
394}
395
396/*
397 * encrypt/decrypt
398 */
399CSSM_RETURN buEncryptDecrypt(
400	BU_KEY				key,
401	CSSM_BOOL			forEncrypt,
402	CSSM_ALGORITHMS		encrAlg,
403	CSSM_ENCRYPT_MODE	mode,				// CSSM_ALGMODE_CBC, etc.
404	const CSSM_DATA		*iv,				//�optional per mode
405	uint32				effectiveKeyBits,	// optional per key alg (actually just RC2)
406											// for RSA, key size in bits
407	uint32				rounds,				// optional, RC5 only
408	const CSSM_DATA		*inData,
409	CSSM_DATA_PTR		outData)			// mallocd and RETURNED
410{
411#if 0 // NO MORE BSAFE
412	B_ALGORITHM_OBJ		alg;
413	int 				brtn;
414	char				fbCipher = 1;
415	uint32				blockSize = 0;
416	unsigned			outBufLen;
417	unsigned			bytesMoved;
418	CSSM_RETURN			crtn;
419	char				useIv;
420
421	// these variables are used in the switch below and need to
422	// live until after setAlgorithm()
423	ITEM	 			bsIv;
424    B_BLK_CIPHER_W_FEEDBACK_PARAMS spec;
425	A_RC5_PARAMS		rc5Params;
426	A_RC2_PARAMS		rc2Params;
427
428	brtn = B_CreateAlgorithmObject(&alg);
429	if(brtn) {
430		return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject");
431	}
432
433	/* per-alg setup */
434	switch(encrAlg) {
435		case CSSM_ALGID_RC4:
436			/* the easy one */
437			brtn = B_SetAlgorithmInfo(alg, AI_RC4, NULL);
438			if(brtn) {
439				crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
440				goto abort;
441			}
442			fbCipher = 0;
443			break;
444
445		case CSSM_ALGID_RSA:
446			/* assume encrypt via publicm decrypt via private */
447			if(forEncrypt) {
448				brtn = B_SetAlgorithmInfo(alg, AI_PKCS_RSAPublic, NULL);
449			}
450			else {
451				brtn = B_SetAlgorithmInfo(alg, AI_PKCS_RSAPrivate, NULL);
452			}
453			if(brtn) {
454				crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo(RSA)");
455				goto abort;
456			}
457			blockSize = (effectiveKeyBits + 7) / 8;
458			fbCipher = 0;
459			break;
460
461		/* common code using AI_FeebackCipher */
462        case CSSM_ALGID_DES:
463            spec.encryptionMethodName = (POINTER)"des";
464			blockSize = 8;
465            break;
466        case CSSM_ALGID_DESX:
467            spec.encryptionMethodName = (POINTER)"desx";
468 			blockSize = 8;
469			break;
470        case CSSM_ALGID_3DES_3KEY_EDE:
471            spec.encryptionMethodName = (POINTER)"des_ede";
472			blockSize = 8;
473            break;
474        case CSSM_ALGID_RC5:
475            spec.encryptionMethodName = (POINTER)"rc5";
476			spec.encryptionParams = (POINTER)&rc5Params;
477			rc5Params.version = 0x10;
478			rc5Params.rounds = rounds;
479			rc5Params.wordSizeInBits = 32;
480			blockSize = 8;
481            break;
482        case CSSM_ALGID_RC2:
483            spec.encryptionMethodName = (POINTER)"rc2";
484			spec.encryptionParams = (POINTER)&rc2Params;
485			rc2Params.effectiveKeyBits = effectiveKeyBits;
486 			blockSize = 8;
487           break;
488		/* add other non-AI_FeebackCipher algorithms here */
489		default:
490			printf("buEncryptDecrypt: unknown algorithm\n");
491			return CSSM_ERRCODE_INTERNAL_ERROR;
492	}
493	if(fbCipher) {
494		useIv = 1;		// default, except for ECB
495		switch(mode) {
496			case CSSM_ALGMODE_CBCPadIV8:
497				spec.feedbackMethodName = (POINTER)"cbc";
498				spec.paddingMethodName = (POINTER)"pad";
499				break;
500			case CSSM_ALGMODE_CBC_IV8:
501				spec.feedbackMethodName = (POINTER)"cbc";
502				spec.paddingMethodName = (POINTER)"nopad";
503				break;
504			case CSSM_ALGMODE_OFB_IV8:
505				spec.feedbackMethodName = (POINTER)"cbc";
506				spec.paddingMethodName = (POINTER)"nopad";
507				break;
508			case CSSM_ALGMODE_ECB:
509				/* this does not seem to work yet - need info from
510				 * RSA. Specify block size as the feedbackParams (per manual)
511				 * and get a memmove error trying to copy from address 8; specify
512				 * an IV and get BSAFE error 524 (BE_INPUT_DATA) error on the
513				 * EncryptInit.
514				 */
515				spec.feedbackMethodName = (POINTER)"ecb";
516				spec.paddingMethodName = (POINTER)"nopad";
517				//useIv = 0;
518				//spec.feedbackParams = (POINTER)8;
519				break;
520			default:
521				printf("buEncryptDecrypt: unknown mode\n");
522				return CSSM_ERRCODE_INTERNAL_ERROR;
523		}
524		if(useIv && (iv != NULL)) {
525			buCssmDataToItem(iv, &bsIv);
526			spec.feedbackParams = (POINTER)&bsIv;
527		}
528
529		brtn = B_SetAlgorithmInfo(alg, AI_FeedbackCipher, (POINTER)&spec);
530		if(brtn) {
531			crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
532			goto abort;
533		}
534	}
535
536	/*
537	 * OK, one way or another we have an algorithm object. Set up
538	 * output buffer.
539	 */
540	if(forEncrypt) {
541		outBufLen = inData->Length + blockSize;
542	}
543	else {
544		outBufLen = inData->Length;
545	}
546	outData->Length = 0;
547	outData->Data = NULL;
548	crtn = appSetupCssmData(outData, outBufLen);
549	if(crtn) {
550		goto abort;
551	}
552	if(forEncrypt) {
553		brtn = B_EncryptInit(alg,
554			(B_KEY_OBJ)key,
555			BSAFE_ALGORITHM_CHOOSER,
556			(A_SURRENDER_CTX *)NULL);
557		if(brtn) {
558			crtn = buBsafeErrToCssm(brtn, "B_EncryptInit");
559			goto abort;
560		}
561		brtn = B_EncryptUpdate(alg,
562			outData->Data,
563			&bytesMoved,
564			outBufLen,
565			inData->Data,
566			inData->Length,
567			buGetRng(),		// randAlg
568			NULL);			// surrender
569		if(brtn) {
570			crtn = buBsafeErrToCssm(brtn, "B_EncryptInit");
571			goto abort;
572		}
573		outData->Length = bytesMoved;
574		brtn = B_EncryptFinal(alg,
575			outData->Data + bytesMoved,
576			&bytesMoved,
577			outBufLen - outData->Length,
578			buGetRng(),		// randAlg
579			NULL);			// surrender
580		if(brtn) {
581			crtn = buBsafeErrToCssm(brtn, "B_EncryptFinal");
582			goto abort;
583		}
584		outData->Length += bytesMoved;
585		crtn = CSSM_OK;
586	}
587	else {
588		brtn = B_DecryptInit(alg,
589			(B_KEY_OBJ)key,
590			BSAFE_ALGORITHM_CHOOSER,
591			(A_SURRENDER_CTX *)NULL);
592		if(brtn) {
593			crtn = buBsafeErrToCssm(brtn, "B_DecryptInit");
594			goto abort;
595		}
596		brtn = B_DecryptUpdate(alg,
597			outData->Data,
598			&bytesMoved,
599			outBufLen,
600			inData->Data,
601			inData->Length,
602			NULL,			// randAlg
603			NULL);			// surrender
604		if(brtn) {
605			crtn = buBsafeErrToCssm(brtn, "B_DecryptUpdate");
606			goto abort;
607		}
608		outData->Length = bytesMoved;
609		brtn = B_DecryptFinal(alg,
610			outData->Data + bytesMoved,
611			&bytesMoved,
612			outBufLen - outData->Length,
613			NULL,			// randAlg
614			NULL);			// surrender
615		if(brtn) {
616			crtn = buBsafeErrToCssm(brtn, "B_DecryptFinal");
617			goto abort;
618		}
619		outData->Length += bytesMoved;
620		crtn = CSSM_OK;
621	}
622abort:
623	B_DestroyAlgorithmObject(&alg);
624#endif
625	return 0;   //crtn;
626}
627
628#if 0
629/* CSSM sig alg --> B_INFO_TYPE */
630static CSSM_RETURN cssmSigAlgToInfoType(
631	CSSM_ALGORITHMS cssmAlg,
632	B_INFO_TYPE		*infoType)
633{
634	switch(cssmAlg) {
635		case CSSM_ALGID_SHA1WithRSA:
636			*infoType = AI_SHA1WithRSAEncryption;
637			break;
638		case CSSM_ALGID_MD5WithRSA:
639			*infoType = AI_MD5WithRSAEncryption;
640			break;
641		case CSSM_ALGID_SHA1WithDSA:
642			*infoType = AI_DSAWithSHA1;
643			break;
644		default:
645			printf("cssmSigAlgToInfoType: unknown algorithm\n");
646			return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
647	}
648	return CSSM_OK;
649}
650#endif
651
652/*
653 * Sign/verify
654 */
655CSSM_RETURN buSign(
656	BU_KEY				key,
657	CSSM_ALGORITHMS		sigAlg,
658	const CSSM_DATA		*ptext,
659	uint32				keySizeInBits,		// to set up sig
660	CSSM_DATA_PTR		sig)				// mallocd and RETURNED
661{
662#if 0 // NO MORE BSAFE
663	B_ALGORITHM_OBJ		alg = NULL;
664	int 				brtn;
665	B_INFO_TYPE			infoType;
666	CSSM_RETURN			crtn;
667	unsigned			sigBytes;
668
669	brtn = B_CreateAlgorithmObject(&alg);
670	if(brtn) {
671		return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject");
672	}
673	crtn = cssmSigAlgToInfoType(sigAlg, &infoType);
674	if(crtn) {
675		return crtn;
676	}
677	brtn = B_SetAlgorithmInfo(alg, infoType, NULL);
678	if(brtn) {
679		crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
680		goto abort;
681	}
682	brtn = B_SignInit(alg, (B_KEY_OBJ)key, BSAFE_ALGORITHM_CHOOSER, NULL);
683	if(brtn) {
684		crtn = buBsafeErrToCssm(brtn, "B_SignInit");
685		goto abort;
686	}
687	brtn = B_SignUpdate(alg, ptext->Data, ptext->Length, NULL);
688	if(brtn) {
689		crtn = buBsafeErrToCssm(brtn, "B_SignUpdate");
690		goto abort;
691	}
692
693	/* prepare for sig, size of key */
694	sigBytes = (keySizeInBits + 7) / 8;
695	sig->Data = (uint8 *)CSSM_MALLOC(sigBytes);
696	sig->Length = sigBytes;
697
698	brtn = B_SignFinal(alg, sig->Data, &sigBytes, sigBytes, buGetRng(), NULL);
699	if(brtn) {
700		crtn = buBsafeErrToCssm(brtn, "B_SignFinal");
701		goto abort;
702	}
703	sig->Length = sigBytes;
704	crtn = CSSM_OK;
705abort:
706	B_DestroyAlgorithmObject(&alg);
707#endif
708	return 0;//;
709}
710
711CSSM_RETURN buVerify(
712	BU_KEY				key,
713	CSSM_ALGORITHMS		sigAlg,
714	const CSSM_DATA		*ptext,
715	const CSSM_DATA		*sig)				// mallocd and RETURNED
716{
717#if 0 // NO MORE BSAFE
718	B_ALGORITHM_OBJ		alg = NULL;
719	int 				brtn;
720	B_INFO_TYPE			infoType;
721	CSSM_RETURN			crtn;
722
723	brtn = B_CreateAlgorithmObject(&alg);
724	if(brtn) {
725		return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject");
726	}
727	crtn = cssmSigAlgToInfoType(sigAlg, &infoType);
728	if(crtn) {
729		return crtn;
730	}
731	brtn = B_SetAlgorithmInfo(alg, infoType, NULL);
732	if(brtn) {
733		crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
734		goto abort;
735	}
736	brtn = B_VerifyInit(alg, (B_KEY_OBJ)key, BSAFE_ALGORITHM_CHOOSER, NULL);
737	if(brtn) {
738		crtn = buBsafeErrToCssm(brtn, "B_VerifyInit");
739		goto abort;
740	}
741	brtn = B_VerifyUpdate(alg, ptext->Data, ptext->Length, NULL);
742	if(brtn) {
743		crtn = buBsafeErrToCssm(brtn, "B_VerifyUpdate");
744		goto abort;
745	}
746	brtn = B_VerifyFinal(alg, sig->Data, sig->Length, buGetRng(), NULL);
747	if(brtn) {
748		crtn = buBsafeErrToCssm(brtn, "B_VerifyFinal");
749		goto abort;
750	}
751	crtn = CSSM_OK;
752abort:
753	B_DestroyAlgorithmObject(&alg);
754	return crtn;
755#endif
756    return 0;
757}
758
759/*
760 * generate MAC either one update (updateSizes == NULL) or
761 * specified set of update sizes.
762 */
763#define MAX_MAC_SIZE	20
764
765CSSM_RETURN buGenMac(
766	BU_KEY				key,				// any key, any size
767	CSSM_ALGORITHMS		macAlg,				// only CSSM_ALGID_SHA1HMAC for now
768	const CSSM_DATA		*ptext,
769	unsigned			*updateSizes,		// NULL --> random updates
770											// else null-terminated list of sizes
771	CSSM_DATA_PTR		mac)				// mallocd and RETURNED
772{
773#if 0 // NO MORE BSAFE
774	B_ALGORITHM_OBJ		alg = NULL;
775	int 				brtn;
776	CSSM_RETURN			crtn;
777	B_DIGEST_SPECIFIER	digestInfo;
778	B_INFO_TYPE			infoType;
779	unsigned			macBytes;
780
781	brtn = B_CreateAlgorithmObject(&alg);
782	if(brtn) {
783		return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject");
784	}
785	switch(macAlg) {
786		case CSSM_ALGID_SHA1HMAC:
787		case CSSM_ALGID_SHA1HMAC_LEGACY:
788			digestInfo.digestInfoType = AI_SHA1;
789			infoType = AI_HMAC;
790			break;
791		default:
792			printf("buGenMac: alg not supported\n");
793			return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
794	}
795	digestInfo.digestInfoParams = NULL;
796	brtn = B_SetAlgorithmInfo(alg, infoType, (POINTER)&digestInfo);
797	if(brtn) {
798		crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
799		goto abort;
800	}
801	brtn = B_DigestInit(alg, (B_KEY_OBJ)key, BSAFE_ALGORITHM_CHOOSER, NULL);
802	if(brtn) {
803		crtn = buBsafeErrToCssm(brtn, "B_DigestInit");
804		goto abort;
805	}
806	if(updateSizes) {
807		uint8 *currData = ptext->Data;
808		while(*updateSizes) {
809			brtn = B_DigestUpdate(alg, currData, *updateSizes, NULL);
810			if(brtn) {
811				crtn = buBsafeErrToCssm(brtn, "B_DigestUpdate");
812				goto abort;
813			}
814			currData += *updateSizes;
815			updateSizes++;
816		}
817	}
818	else {
819		/* one-shot */
820		brtn = B_DigestUpdate(alg, ptext->Data, ptext->Length, NULL);
821		if(brtn) {
822			crtn = buBsafeErrToCssm(brtn, "B_DigestUpdate");
823			goto abort;
824		}
825	}
826	/* prepare for mac, magically gleaned max size */
827	macBytes = MAX_MAC_SIZE;
828	mac->Data = (uint8 *)CSSM_MALLOC(macBytes);
829	mac->Length = macBytes;
830
831	brtn = B_DigestFinal(alg, mac->Data, &macBytes, macBytes, NULL);
832	if(brtn) {
833		crtn = buBsafeErrToCssm(brtn, "B_DigestFinal");
834		goto abort;
835	}
836	mac->Length = macBytes;
837	crtn = CSSM_OK;
838abort:
839	B_DestroyAlgorithmObject(&alg);
840	return crtn;
841#endif
842    return 0;
843}
844
845/* generate digest */
846#define MAX_DIGEST_SIZE		20
847
848CSSM_RETURN buGenDigest(
849	CSSM_ALGORITHMS		macAlg,				// CSSM_ALGID_SHA1, etc. */
850	const CSSM_DATA		*ptext,
851	CSSM_DATA_PTR		digest)				// mallocd and RETURNED
852{
853#if 0 // NO MORE BSAFE
854	B_ALGORITHM_OBJ		alg = NULL;
855	int 				brtn;
856	CSSM_RETURN			crtn;
857	B_INFO_TYPE			infoType;
858	unsigned			hashBytes;
859
860	brtn = B_CreateAlgorithmObject(&alg);
861	if(brtn) {
862		return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject");
863	}
864	switch(macAlg) {
865		case CSSM_ALGID_SHA1:
866			infoType = AI_SHA1;
867			break;
868		case CSSM_ALGID_MD5:
869			infoType = AI_MD5;
870			break;
871		case CSSM_ALGID_MD2:
872			infoType = AI_MD2;
873			break;
874		default:
875			printf("buGenDigest: alg not supported\n");
876			return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
877	}
878	brtn = B_SetAlgorithmInfo(alg, infoType, NULL);
879	if(brtn) {
880		crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
881		goto abort;
882	}
883	brtn = B_DigestInit(alg, NULL, BSAFE_ALGORITHM_CHOOSER, NULL);
884	if(brtn) {
885		crtn = buBsafeErrToCssm(brtn, "B_DigestInit");
886		goto abort;
887	}
888	brtn = B_DigestUpdate(alg, ptext->Data, ptext->Length, NULL);
889	if(brtn) {
890		crtn = buBsafeErrToCssm(brtn, "B_DigestUpdate");
891		goto abort;
892	}
893
894	/* prepare for digest, magically gleaned max size */
895	hashBytes = MAX_DIGEST_SIZE;
896	digest->Data = (uint8 *)CSSM_MALLOC(hashBytes);
897	digest->Length = hashBytes;
898
899	brtn = B_DigestFinal(alg, digest->Data, &hashBytes, hashBytes, NULL);
900	if(brtn) {
901		crtn = buBsafeErrToCssm(brtn, "B_DigestFinal");
902		goto abort;
903	}
904	digest->Length = hashBytes;
905	crtn = CSSM_OK;
906abort:
907	B_DestroyAlgorithmObject(&alg);
908	return crtn;
909#else
910    return 0;
911#endif
912}
913
914/*
915 * Convert between BSAFE and CDSA private keys
916 */
917CSSM_RETURN buBsafePrivKeyToCdsa(
918	CSSM_ALGORITHMS		keyAlg,
919	uint32				keySizeInBits,
920	BU_KEY				bsafePrivKey,
921	CSSM_KEY_PTR		cdsaPrivKey)
922{
923#if 0 // NO MORE BSAFE
924	B_INFO_TYPE			infoType;
925	ITEM				*keyBlob;
926	int					brtn;
927	CSSM_KEYBLOB_FORMAT	format;
928	CSSM_KEYHEADER_PTR	hdr = &cdsaPrivKey->KeyHeader;
929
930	/* what kind of info? */
931	switch(keyAlg) {
932		case CSSM_ALGID_RSA:
933			infoType = KI_PKCS_RSAPrivateBER;
934			format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
935			break;
936		case CSSM_ALGID_DSA:
937			infoType = KI_DSAPrivateBER;
938			format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
939			break;
940		default:
941			printf("***buBsafePrivKeyToCdsa: bogus keyAlg\n");
942			return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
943	}
944
945	/* get the blob */
946	brtn = B_GetKeyInfo((POINTER *)&keyBlob,
947		(B_KEY_OBJ)bsafePrivKey,
948		infoType);
949	if(brtn) {
950		return buBsafeErrToCssm(brtn, "B_GetKeyInfo");
951	}
952
953	/* copy blob to CDSA key */
954	cdsaPrivKey->KeyData.Data = (uint8 *)CSSM_MALLOC(keyBlob->len);
955	cdsaPrivKey->KeyData.Length = keyBlob->len;
956	memmove(cdsaPrivKey->KeyData.Data, keyBlob->data, keyBlob->len);
957
958	/* set up CSSM key header */
959	memset(hdr, 0, sizeof(CSSM_KEYHEADER));
960	hdr->HeaderVersion = CSSM_KEYHEADER_VERSION;
961	hdr->BlobType = CSSM_KEYBLOB_RAW;
962	hdr->Format = format;
963	hdr->AlgorithmId = keyAlg;
964	hdr->KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
965	hdr->LogicalKeySizeInBits = keySizeInBits;
966	hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
967	hdr->KeyUsage = CSSM_KEYUSE_ANY;
968#endif
969	return CSSM_OK;
970}
971
972CSSM_RETURN buCdsaPrivKeyToBsafe(
973	CSSM_KEY_PTR		cdsaPrivKey,
974	BU_KEY				*bsafePrivKey)
975{
976#if 0 // NO MORE BSAFE
977	int 		brtn;
978	B_KEY_OBJ	privKey = NULL;
979	ITEM		keyBlob;
980	B_INFO_TYPE	infoType;
981
982	/* what kind of info? */
983	switch(cdsaPrivKey->KeyHeader.AlgorithmId) {
984		case CSSM_ALGID_RSA:
985			infoType = KI_PKCS_RSAPrivateBER;
986			break;
987		case CSSM_ALGID_DSA:
988			infoType = KI_DSAPrivateBER;
989			break;
990		default:
991			printf("***buCdsaPrivKeyToCssm: bogus keyAlg\n");
992			return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
993	}
994
995	/* create caller's key, assign blob to it */
996	brtn = B_CreateKeyObject(&privKey);
997	if(brtn) {
998		return buBsafeErrToCssm(brtn, "B_CreateKeyObject");
999	}
1000	buCssmDataToItem(&cdsaPrivKey->KeyData, &keyBlob);
1001	brtn = B_SetKeyInfo(privKey, infoType, (POINTER)&keyBlob);
1002	if(brtn) {
1003		return buBsafeErrToCssm(brtn, "B_SetKeyInfo");
1004	}
1005	*bsafePrivKey = privKey;
1006#endif
1007	return CSSM_OK;
1008}
1009
1010