]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/cspxutils/utilLib/bsafeUtils.c
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / utilLib / bsafeUtils.c
diff --git a/SecurityTests/cspxutils/utilLib/bsafeUtils.c b/SecurityTests/cspxutils/utilLib/bsafeUtils.c
new file mode 100644 (file)
index 0000000..9038a26
--- /dev/null
@@ -0,0 +1,1009 @@
+/*
+ * bsafeUtils.c - common routines for CDSA/BSAFE compatibility testing
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+//#include <security_bsafe/bsafe.h>
+//#include <security_bsafe/aglobal.h>
+#include "bsafeUtils.h"
+#include <Security/cssmerr.h>
+#include "common.h"
+
+/*
+ * Convert between BSAFE ITEM and CSSM_DATA
+ */
+#if 0
+static inline void buItemToCssmData(
+       const ITEM              *item,
+       CSSM_DATA_PTR   cdata)
+{
+       cdata->Data   = item->data;
+       cdata->Length = item->len;
+}
+
+static inline void buCssmDataToItem(
+       const CSSM_DATA         *cdata,
+       ITEM                            *item)
+{
+       item->data = cdata->Data;
+       item->len  = cdata->Length;
+}
+
+/*
+ * BSafe's Chooser table - all we'll ever need.
+ */
+/*static*/ B_ALGORITHM_METHOD *BSAFE_ALGORITHM_CHOOSER[] = {
+    // digests
+    &AM_SHA,
+    &AM_MD5,
+       &AM_MD2,
+
+    // organizational
+    &AM_CBC_ENCRYPT,
+    &AM_CBC_DECRYPT,
+    &AM_ECB_ENCRYPT,
+    &AM_ECB_DECRYPT,
+    &AM_OFB_ENCRYPT,
+    &AM_OFB_DECRYPT,
+
+    // DES & variants
+    &AM_DES_ENCRYPT,
+    &AM_DES_DECRYPT,
+    &AM_DESX_ENCRYPT,
+    &AM_DESX_DECRYPT,
+    &AM_DES_EDE_ENCRYPT,
+    &AM_DES_EDE_DECRYPT,
+
+    // RCn stuff
+    &AM_RC2_CBC_ENCRYPT,
+    &AM_RC2_CBC_DECRYPT,
+    &AM_RC2_ENCRYPT,
+    &AM_RC2_DECRYPT,
+    &AM_RC4_ENCRYPT,
+    &AM_RC4_DECRYPT,
+    &AM_RC5_ENCRYPT,
+    &AM_RC5_DECRYPT,
+    &AM_RC5_CBC_ENCRYPT,
+    &AM_RC5_CBC_DECRYPT,
+
+    // RSA
+    &AM_RSA_STRONG_KEY_GEN,
+    &AM_RSA_KEY_GEN,
+    &AM_RSA_CRT_ENCRYPT_BLIND,
+    &AM_RSA_CRT_DECRYPT_BLIND,
+    &AM_RSA_ENCRYPT,
+    &AM_RSA_DECRYPT,
+
+    // DSA
+    &AM_DSA_PARAM_GEN,
+    &AM_DSA_KEY_GEN,
+
+    // signatures
+    &AM_DSA_SIGN,
+    &AM_DSA_VERIFY,
+
+    // random number generation
+    &AM_MD5_RANDOM,
+    &AM_SHA_RANDOM,
+
+    // sentinel
+    (B_ALGORITHM_METHOD *)NULL_PTR
+};
+
+/* 
+ * Convert a BSAFE return to a CSSM error and optionally print the error msg with 
+ * the op in which the error occurred.
+ */
+static CSSM_RETURN buBsafeErrToCssm(
+       int brtn, 
+       const char *op)
+{
+       const char *errStr = NULL;
+       CSSM_RETURN crtn;
+       
+    switch (brtn) {
+               case 0:
+                       return CSSM_OK;
+               case BE_ALLOC:
+                       crtn = CSSMERR_CSSM_MEMORY_ERROR;
+                       errStr = "BE_ALLOC";
+                       break;
+               case BE_SIGNATURE:
+                       crtn = CSSMERR_CSP_VERIFY_FAILED;
+                       errStr = "BE_SIGNATURE";
+                       break;
+               case BE_OUTPUT_LEN:
+                       crtn = CSSMERR_CSP_OUTPUT_LENGTH_ERROR;
+                       errStr = "BE_OUTPUT_LEN";
+                       break;
+               case BE_INPUT_LEN:
+                       crtn = CSSMERR_CSP_INPUT_LENGTH_ERROR;
+                       errStr = "BE_INPUT_LEN";
+                       break;
+               case BE_EXPONENT_EVEN:
+                       crtn = CSSMERR_CSP_INVALID_KEY;
+                       errStr = "BE_EXPONENT_EVEN";
+                       break;
+               case BE_EXPONENT_LEN:
+                       crtn = CSSMERR_CSP_INVALID_KEY;
+                       errStr = "BE_EXPONENT_LEN";
+                       break;
+               case BE_EXPONENT_ONE:
+                       crtn = CSSMERR_CSP_INVALID_KEY;
+                       errStr = "BE_EXPONENT_ONE";
+                       break;
+               case BE_DATA:
+                       crtn = CSSMERR_CSP_INVALID_DATA;
+                       errStr = "BE_DATA";
+                       break;
+               case BE_INPUT_DATA:
+                       crtn = CSSMERR_CSP_INVALID_DATA;
+                       errStr = "BE_INPUT_DATA";
+                       break;
+               case BE_WRONG_KEY_INFO:
+                       crtn = CSSMERR_CSP_INVALID_KEY;
+                       errStr = "BE_WRONG_KEY_INFO";
+                       break;
+        default:
+                       //@@@ translate BSafe errors intelligently
+                       crtn = CSSM_ERRCODE_INTERNAL_ERROR;
+                       errStr = "Other BSAFE error";
+                       break;
+    }
+       if(op != NULL) {
+               printf("%s: BSAFE error %d (%s)\n", op, brtn, errStr);
+       }
+       return crtn;
+}
+
+/*
+ * Non-thread-safe global random B_ALGORITHM_OBJ and a reusable init for it.
+ */
+static B_ALGORITHM_OBJ         bsafeRng = NULL;
+#define BSAFE_RANDSIZE 64
+
+static B_ALGORITHM_OBJ buGetRng()
+{
+       int brtn;
+       uint8 seed[BSAFE_RANDSIZE];
+       
+       if(bsafeRng != NULL) {
+               return bsafeRng;
+       }
+       brtn = B_CreateAlgorithmObject(&bsafeRng);
+       if(brtn) {
+               buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject(&bsafeRng)");
+               return NULL;
+       }
+       brtn = B_SetAlgorithmInfo(bsafeRng, AI_X962Random_V0, NULL_PTR);
+       if(brtn) {
+               buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo(bsafeRng)");
+               return NULL;
+       }
+       brtn = B_RandomInit(bsafeRng, BSAFE_ALGORITHM_CHOOSER, NULL);
+       if(brtn) {
+               buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo(bsafeRng)");
+               return NULL;
+       }
+       appGetRandomBytes(seed, BSAFE_RANDSIZE);
+       brtn = B_RandomUpdate(bsafeRng, seed, BSAFE_RANDSIZE, NULL);
+       if(brtn) {
+               buBsafeErrToCssm(brtn, "B_RandomUpdate");
+               return NULL;
+       }
+       return bsafeRng;
+}
+#endif
+
+/*
+ * Create a symmetric key.
+ */
+CSSM_RETURN  buGenSymKey(
+       uint32                  keySizeInBits,
+       const CSSM_DATA *keyData,
+       BU_KEY                  *key)                   // RETURNED
+{
+#if 0
+       int                             brtn;
+       B_KEY_OBJ               bkey = NULL;
+       ITEM                    item;
+       unsigned                keyBytes = (keySizeInBits + 7) / 8;
+       
+       if(keyBytes > keyData->Length) {
+               /* note it's OK to give us too much key data */
+               printf("***buGenSymKey: Insufficient keyData\n");
+               return CSSM_ERRCODE_INTERNAL_ERROR;
+       }
+
+       /* create a BSAFE key */
+       brtn = B_CreateKeyObject(&bkey);
+       if(brtn) {
+               return buBsafeErrToCssm(brtn, "B_CreateKeyObject");
+       }
+       
+       /* assign data to the key */
+       item.data = keyData->Data;
+       item.len = keyBytes;
+       brtn = B_SetKeyInfo(bkey, KI_Item, (POINTER)&item);
+       if(brtn) {
+               return buBsafeErrToCssm(brtn, "B_SetKeyInfo");
+       }
+       else {
+               *key = bkey;
+               return CSSM_OK;
+       }
+#endif
+    return 0;
+}
+
+/*
+ * Create asymmetric key pair.
+ * FIXME - additional params (e.g. DSA params, RSA exponent)?
+ */
+CSSM_RETURN buGenKeyPair(
+       uint32                  keySizeInBits,
+       CSSM_ALGORITHMS keyAlg,                 // CSSM_ALGID_{RSA,DSA}
+       BU_KEY                  *pubKey,                // RETURNED
+       BU_KEY                  *privKey)               // RETURNED
+{
+#if 0 // NO MORE BSAFE
+       int                                             brtn;
+       B_KEY_OBJ                               bPubkey = NULL;
+       B_KEY_OBJ                               bPrivkey = NULL;
+       B_ALGORITHM_OBJ                 keypairGen = NULL;
+       const char                              *op = NULL;
+       A_RSA_KEY_GEN_PARAMS    params;
+       unsigned char                   exp[1] = { 3 };
+    B_ALGORITHM_OBJ            genDsaAlg = NULL;
+    B_ALGORITHM_OBJ            dsaResult = NULL;
+       B_DSA_PARAM_GEN_PARAMS  dsaParams;
+       A_DSA_PARAMS                    *kParams = NULL;
+       
+       /* create algorithm object */
+       brtn = B_CreateAlgorithmObject(&keypairGen);
+       if(brtn) {
+               return CSSMERR_CSSM_MEMORY_ERROR;
+       }
+       
+       /* create two BSAFE keys */
+       brtn = B_CreateKeyObject(&bPubkey);
+       if(brtn) {
+               op ="B_CreateKeyObject";
+               goto abort;
+       }
+       brtn = B_CreateKeyObject(&bPrivkey);
+       if(brtn) {
+               op ="B_CreateKeyObject";
+               goto abort;
+       }
+       switch(keyAlg) {
+               case CSSM_ALGID_RSA:
+               {
+                       /* set RSA-specific params */
+                       params.modulusBits = keySizeInBits;
+                       /* hack - parameterize? */
+                       params.publicExponent.data = exp;
+                       params.publicExponent.len = 1;
+                       brtn = B_SetAlgorithmInfo(keypairGen, AI_RSAKeyGen, 
+                               (POINTER)&params);
+                       if(brtn) {
+                               op ="B_SetAlgorithmInfo(AI_RSAKeyGen)";
+                       }
+                       break;
+               }
+               case CSSM_ALGID_DSA:    
+               {
+                       /* jump through hoops generating parameters */
+                       brtn = B_CreateAlgorithmObject(&genDsaAlg);
+                       if(brtn) {
+                               op ="B_CreateAlgorithmObject";
+                               break;
+                       }
+                       dsaParams.primeBits = keySizeInBits;
+               brtn = B_SetAlgorithmInfo(genDsaAlg, AI_DSAParamGen, (POINTER)&dsaParams);
+                       if(brtn) {
+                               op = "B_SetAlgorithmInfo(AI_DSAParamGen)";
+                               break;
+                       }
+                       brtn = B_GenerateInit(genDsaAlg, BSAFE_ALGORITHM_CHOOSER, NULL);
+                       if(brtn) {
+                               op = "B_GenerateInit(AI_DSAParamGen)";
+                               break;
+                       }
+               brtn = B_CreateAlgorithmObject(&dsaResult);
+                       if(brtn) {
+                               op = "B_CreateAlgorithmObject";
+                               break;
+                       }
+               brtn = B_GenerateParameters(genDsaAlg, dsaResult, buGetRng(), NULL);
+                       if(brtn) {
+                               op = "B_GenerateParameters";
+                               break;
+                       }
+                       
+                       /* dsaResult now has the parameters, which we must extract and then
+                        * apply to the keypairGen object. Cool, huh? */
+                       brtn = B_GetAlgorithmInfo((POINTER *)&kParams, dsaResult, AI_DSAKeyGen);
+                       if(brtn) {
+                               op = "B_GetAlgorithmInfo(AI_DSAKeyGen)";
+                               break;
+                       }
+                       brtn = B_SetAlgorithmInfo(keypairGen, AI_DSAKeyGen, (POINTER)kParams);
+                       if(brtn) {
+                               op ="B_SetAlgorithmInfo(AI_DSAKeyGen)";
+                       }
+                       break;
+               }
+               default:
+                       printf("buGenKeyPair: algorithm not supported\n");
+                       return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
+       }
+       if(brtn) {
+               goto abort;
+       }
+       
+       /* keypairGen all set to go. */
+       brtn = B_GenerateInit(keypairGen, 
+               BSAFE_ALGORITHM_CHOOSER,
+               (A_SURRENDER_CTX *)NULL);
+       if(brtn) {
+               op = "B_GenerateInit";
+               goto abort;
+       }
+       brtn = B_GenerateKeypair(keypairGen,
+               bPubkey,
+               bPrivkey,
+               buGetRng(),
+               NULL);
+       if(brtn) {
+               op = "B_GenerateInit";
+       }
+abort:
+       B_DestroyAlgorithmObject(&keypairGen);
+       B_DestroyAlgorithmObject(&genDsaAlg);
+       B_DestroyAlgorithmObject(&dsaResult);
+       if(brtn) {
+               B_DestroyKeyObject(&bPubkey);
+               B_DestroyKeyObject(&bPrivkey);
+               return buBsafeErrToCssm(brtn, op);
+       }
+       else {
+               *pubKey = bPubkey;
+               *privKey = bPrivkey;
+               return CSSM_OK;
+       }
+#endif
+       return CSSM_OK;
+}
+
+/*
+ * Free a key created in buGenSymKey or buGenKeyPair
+ */
+CSSM_RETURN buFreeKey(
+       BU_KEY                  key)
+{
+#if 0 // NO MORE BSAFE
+       B_KEY_OBJ bkey = (B_KEY_OBJ)key;
+       B_DestroyKeyObject(&bkey);
+#endif
+       return CSSM_OK;
+}
+
+/*
+ * encrypt/decrypt
+ */
+CSSM_RETURN buEncryptDecrypt(
+       BU_KEY                          key,
+       CSSM_BOOL                       forEncrypt,
+       CSSM_ALGORITHMS         encrAlg,
+       CSSM_ENCRYPT_MODE       mode,                           // CSSM_ALGMODE_CBC, etc.
+       const CSSM_DATA         *iv,                            //ĂŠoptional per mode
+       uint32                          effectiveKeyBits,       // optional per key alg (actually just RC2)
+                                                                                       // for RSA, key size in bits
+       uint32                          rounds,                         // optional, RC5 only
+       const CSSM_DATA         *inData,
+       CSSM_DATA_PTR           outData)                        // mallocd and RETURNED
+{
+#if 0 // NO MORE BSAFE
+       B_ALGORITHM_OBJ         alg;
+       int                             brtn;
+       char                            fbCipher = 1;
+       uint32                          blockSize = 0;
+       unsigned                        outBufLen;
+       unsigned                        bytesMoved;
+       CSSM_RETURN                     crtn;
+       char                            useIv;
+       
+       // these variables are used in the switch below and need to 
+       // live until after setAlgorithm()
+       ITEM                            bsIv;
+    B_BLK_CIPHER_W_FEEDBACK_PARAMS spec;
+       A_RC5_PARAMS            rc5Params;
+       A_RC2_PARAMS            rc2Params;
+       
+       brtn = B_CreateAlgorithmObject(&alg);
+       if(brtn) {
+               return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject");
+       }
+       
+       /* per-alg setup */
+       switch(encrAlg) {
+               case CSSM_ALGID_RC4:
+                       /* the easy one */
+                       brtn = B_SetAlgorithmInfo(alg, AI_RC4, NULL);
+                       if(brtn) {
+                               crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
+                               goto abort;
+                       }
+                       fbCipher = 0;
+                       break;
+                       
+               case CSSM_ALGID_RSA:
+                       /* assume encrypt via publicm decrypt via private */
+                       if(forEncrypt) {
+                               brtn = B_SetAlgorithmInfo(alg, AI_PKCS_RSAPublic, NULL);
+                       }
+                       else {
+                               brtn = B_SetAlgorithmInfo(alg, AI_PKCS_RSAPrivate, NULL);
+                       }
+                       if(brtn) {
+                               crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo(RSA)");
+                               goto abort;
+                       }
+                       blockSize = (effectiveKeyBits + 7) / 8;
+                       fbCipher = 0;
+                       break;
+                       
+               /* common code using AI_FeebackCipher */
+        case CSSM_ALGID_DES:
+            spec.encryptionMethodName = (POINTER)"des";
+                       blockSize = 8;
+            break;
+        case CSSM_ALGID_DESX:
+            spec.encryptionMethodName = (POINTER)"desx";
+                       blockSize = 8;
+                       break;
+        case CSSM_ALGID_3DES_3KEY_EDE:
+            spec.encryptionMethodName = (POINTER)"des_ede";
+                       blockSize = 8;
+            break;
+        case CSSM_ALGID_RC5:
+            spec.encryptionMethodName = (POINTER)"rc5";
+                       spec.encryptionParams = (POINTER)&rc5Params;
+                       rc5Params.version = 0x10;
+                       rc5Params.rounds = rounds;
+                       rc5Params.wordSizeInBits = 32;
+                       blockSize = 8;
+            break;
+        case CSSM_ALGID_RC2:
+            spec.encryptionMethodName = (POINTER)"rc2";
+                       spec.encryptionParams = (POINTER)&rc2Params;
+                       rc2Params.effectiveKeyBits = effectiveKeyBits;
+                       blockSize = 8;
+           break;
+               /* add other non-AI_FeebackCipher algorithms here */
+               default:
+                       printf("buEncryptDecrypt: unknown algorithm\n");
+                       return CSSM_ERRCODE_INTERNAL_ERROR;
+       }
+       if(fbCipher) {
+               useIv = 1;              // default, except for ECB
+               switch(mode) {
+                       case CSSM_ALGMODE_CBCPadIV8:
+                               spec.feedbackMethodName = (POINTER)"cbc";
+                               spec.paddingMethodName = (POINTER)"pad";
+                               break;
+                       case CSSM_ALGMODE_CBC_IV8: 
+                               spec.feedbackMethodName = (POINTER)"cbc";
+                               spec.paddingMethodName = (POINTER)"nopad";
+                               break;
+                       case CSSM_ALGMODE_OFB_IV8: 
+                               spec.feedbackMethodName = (POINTER)"cbc";
+                               spec.paddingMethodName = (POINTER)"nopad";
+                               break;
+                       case CSSM_ALGMODE_ECB: 
+                               /* this does not seem to work yet - need info from 
+                                * RSA. Specify block size as the feedbackParams (per manual)
+                                * and get a memmove error trying to copy from address 8; specify
+                                * an IV and get BSAFE error 524 (BE_INPUT_DATA) error on the
+                                * EncryptInit.
+                                */
+                               spec.feedbackMethodName = (POINTER)"ecb";
+                               spec.paddingMethodName = (POINTER)"nopad";
+                               //useIv = 0;
+                               //spec.feedbackParams = (POINTER)8;
+                               break;
+                       default:
+                               printf("buEncryptDecrypt: unknown mode\n");
+                               return CSSM_ERRCODE_INTERNAL_ERROR;
+               }
+               if(useIv && (iv != NULL)) {
+                       buCssmDataToItem(iv, &bsIv);
+                       spec.feedbackParams = (POINTER)&bsIv;
+               }
+               
+               brtn = B_SetAlgorithmInfo(alg, AI_FeedbackCipher, (POINTER)&spec);
+               if(brtn) {
+                       crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
+                       goto abort;
+               }
+       }
+       
+       /*
+        * OK, one way or another we have an algorithm object. Set up
+        * output buffer.
+        */
+       if(forEncrypt) {
+               outBufLen = inData->Length + blockSize;
+       }
+       else {
+               outBufLen = inData->Length;
+       }
+       outData->Length = 0;
+       outData->Data = NULL;
+       crtn = appSetupCssmData(outData, outBufLen);
+       if(crtn) {
+               goto abort;
+       }
+       if(forEncrypt) {
+               brtn = B_EncryptInit(alg, 
+                       (B_KEY_OBJ)key,
+                       BSAFE_ALGORITHM_CHOOSER,
+                       (A_SURRENDER_CTX *)NULL);
+               if(brtn) {
+                       crtn = buBsafeErrToCssm(brtn, "B_EncryptInit");
+                       goto abort;
+               }
+               brtn = B_EncryptUpdate(alg,
+                       outData->Data,
+                       &bytesMoved,
+                       outBufLen,
+                       inData->Data,
+                       inData->Length,
+                       buGetRng(),             // randAlg
+                       NULL);                  // surrender
+               if(brtn) {
+                       crtn = buBsafeErrToCssm(brtn, "B_EncryptInit");
+                       goto abort;
+               }
+               outData->Length = bytesMoved;
+               brtn = B_EncryptFinal(alg,
+                       outData->Data + bytesMoved,
+                       &bytesMoved,
+                       outBufLen - outData->Length,
+                       buGetRng(),             // randAlg
+                       NULL);                  // surrender
+               if(brtn) {
+                       crtn = buBsafeErrToCssm(brtn, "B_EncryptFinal");
+                       goto abort;
+               }
+               outData->Length += bytesMoved;
+               crtn = CSSM_OK;
+       }
+       else {
+               brtn = B_DecryptInit(alg, 
+                       (B_KEY_OBJ)key,
+                       BSAFE_ALGORITHM_CHOOSER,
+                       (A_SURRENDER_CTX *)NULL);
+               if(brtn) {
+                       crtn = buBsafeErrToCssm(brtn, "B_DecryptInit");
+                       goto abort;
+               }
+               brtn = B_DecryptUpdate(alg,
+                       outData->Data,
+                       &bytesMoved,
+                       outBufLen,
+                       inData->Data,
+                       inData->Length,
+                       NULL,                   // randAlg
+                       NULL);                  // surrender
+               if(brtn) {
+                       crtn = buBsafeErrToCssm(brtn, "B_DecryptUpdate");
+                       goto abort;
+               }
+               outData->Length = bytesMoved;
+               brtn = B_DecryptFinal(alg,
+                       outData->Data + bytesMoved,
+                       &bytesMoved,
+                       outBufLen - outData->Length,
+                       NULL,                   // randAlg
+                       NULL);                  // surrender
+               if(brtn) {
+                       crtn = buBsafeErrToCssm(brtn, "B_DecryptFinal");
+                       goto abort;
+               }
+               outData->Length += bytesMoved;
+               crtn = CSSM_OK;
+       }
+abort:
+       B_DestroyAlgorithmObject(&alg);
+#endif
+       return 0;   //crtn;
+}
+
+#if 0
+/* CSSM sig alg --> B_INFO_TYPE */
+static CSSM_RETURN cssmSigAlgToInfoType(
+       CSSM_ALGORITHMS cssmAlg,
+       B_INFO_TYPE             *infoType)
+{
+       switch(cssmAlg) {
+               case CSSM_ALGID_SHA1WithRSA:
+                       *infoType = AI_SHA1WithRSAEncryption;
+                       break;
+               case CSSM_ALGID_MD5WithRSA:
+                       *infoType = AI_MD5WithRSAEncryption;
+                       break;
+               case CSSM_ALGID_SHA1WithDSA:
+                       *infoType = AI_DSAWithSHA1;
+                       break;
+               default:
+                       printf("cssmSigAlgToInfoType: unknown algorithm\n");
+                       return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
+       }
+       return CSSM_OK;
+}
+#endif
+
+/*
+ * Sign/verify
+ */
+CSSM_RETURN buSign(
+       BU_KEY                          key,
+       CSSM_ALGORITHMS         sigAlg,
+       const CSSM_DATA         *ptext,
+       uint32                          keySizeInBits,          // to set up sig
+       CSSM_DATA_PTR           sig)                            // mallocd and RETURNED
+{
+#if 0 // NO MORE BSAFE
+       B_ALGORITHM_OBJ         alg = NULL;
+       int                             brtn;
+       B_INFO_TYPE                     infoType;
+       CSSM_RETURN                     crtn;
+       unsigned                        sigBytes;
+       
+       brtn = B_CreateAlgorithmObject(&alg);
+       if(brtn) {
+               return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject");
+       }
+       crtn = cssmSigAlgToInfoType(sigAlg, &infoType);
+       if(crtn) {
+               return crtn;
+       }
+       brtn = B_SetAlgorithmInfo(alg, infoType, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
+               goto abort;
+       }
+       brtn = B_SignInit(alg, (B_KEY_OBJ)key, BSAFE_ALGORITHM_CHOOSER, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_SignInit");
+               goto abort;
+       }
+       brtn = B_SignUpdate(alg, ptext->Data, ptext->Length, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_SignUpdate");
+               goto abort;
+       }
+       
+       /* prepare for sig, size of key */
+       sigBytes = (keySizeInBits + 7) / 8;
+       sig->Data = (uint8 *)CSSM_MALLOC(sigBytes);
+       sig->Length = sigBytes;
+       
+       brtn = B_SignFinal(alg, sig->Data, &sigBytes, sigBytes, buGetRng(), NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_SignFinal");
+               goto abort;
+       }
+       sig->Length = sigBytes;
+       crtn = CSSM_OK;
+abort:
+       B_DestroyAlgorithmObject(&alg);
+#endif
+       return 0;//;
+}
+
+CSSM_RETURN buVerify(
+       BU_KEY                          key,
+       CSSM_ALGORITHMS         sigAlg,
+       const CSSM_DATA         *ptext,
+       const CSSM_DATA         *sig)                           // mallocd and RETURNED
+{
+#if 0 // NO MORE BSAFE
+       B_ALGORITHM_OBJ         alg = NULL;
+       int                             brtn;
+       B_INFO_TYPE                     infoType;
+       CSSM_RETURN                     crtn;
+       
+       brtn = B_CreateAlgorithmObject(&alg);
+       if(brtn) {
+               return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject");
+       }
+       crtn = cssmSigAlgToInfoType(sigAlg, &infoType);
+       if(crtn) {
+               return crtn;
+       }
+       brtn = B_SetAlgorithmInfo(alg, infoType, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
+               goto abort;
+       }
+       brtn = B_VerifyInit(alg, (B_KEY_OBJ)key, BSAFE_ALGORITHM_CHOOSER, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_VerifyInit");
+               goto abort;
+       }
+       brtn = B_VerifyUpdate(alg, ptext->Data, ptext->Length, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_VerifyUpdate");
+               goto abort;
+       }
+       brtn = B_VerifyFinal(alg, sig->Data, sig->Length, buGetRng(), NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_VerifyFinal");
+               goto abort;
+       }
+       crtn = CSSM_OK;
+abort:
+       B_DestroyAlgorithmObject(&alg);
+       return crtn;
+#endif
+    return 0;
+}
+
+/* 
+ * generate MAC either one update (updateSizes == NULL) or 
+ * specified set of update sizes.
+ */
+#define MAX_MAC_SIZE   20
+
+CSSM_RETURN buGenMac(
+       BU_KEY                          key,                            // any key, any size
+       CSSM_ALGORITHMS         macAlg,                         // only CSSM_ALGID_SHA1HMAC for now
+       const CSSM_DATA         *ptext,
+       unsigned                        *updateSizes,           // NULL --> random updates
+                                                                                       // else null-terminated list of sizes
+       CSSM_DATA_PTR           mac)                            // mallocd and RETURNED 
+{
+#if 0 // NO MORE BSAFE
+       B_ALGORITHM_OBJ         alg = NULL;
+       int                             brtn;
+       CSSM_RETURN                     crtn;
+       B_DIGEST_SPECIFIER      digestInfo;
+       B_INFO_TYPE                     infoType;
+       unsigned                        macBytes;
+       
+       brtn = B_CreateAlgorithmObject(&alg);
+       if(brtn) {
+               return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject");
+       }
+       switch(macAlg) {
+               case CSSM_ALGID_SHA1HMAC:
+               case CSSM_ALGID_SHA1HMAC_LEGACY:
+                       digestInfo.digestInfoType = AI_SHA1;
+                       infoType = AI_HMAC;
+                       break;
+               default:
+                       printf("buGenMac: alg not supported\n");
+                       return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
+       }
+       digestInfo.digestInfoParams = NULL;
+       brtn = B_SetAlgorithmInfo(alg, infoType, (POINTER)&digestInfo);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
+               goto abort;
+       }
+       brtn = B_DigestInit(alg, (B_KEY_OBJ)key, BSAFE_ALGORITHM_CHOOSER, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_DigestInit");
+               goto abort;
+       }
+       if(updateSizes) {
+               uint8 *currData = ptext->Data;
+               while(*updateSizes) {
+                       brtn = B_DigestUpdate(alg, currData, *updateSizes, NULL);
+                       if(brtn) {
+                               crtn = buBsafeErrToCssm(brtn, "B_DigestUpdate");
+                               goto abort;
+                       }
+                       currData += *updateSizes;
+                       updateSizes++;
+               }
+       }
+       else {
+               /* one-shot */
+               brtn = B_DigestUpdate(alg, ptext->Data, ptext->Length, NULL);
+               if(brtn) {
+                       crtn = buBsafeErrToCssm(brtn, "B_DigestUpdate");
+                       goto abort;
+               }
+       }
+       /* prepare for mac, magically gleaned max size */
+       macBytes = MAX_MAC_SIZE;
+       mac->Data = (uint8 *)CSSM_MALLOC(macBytes);
+       mac->Length = macBytes;
+       
+       brtn = B_DigestFinal(alg, mac->Data, &macBytes, macBytes, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_DigestFinal");
+               goto abort;
+       }
+       mac->Length = macBytes;
+       crtn = CSSM_OK;
+abort:
+       B_DestroyAlgorithmObject(&alg);
+       return crtn;
+#endif
+    return 0;
+}
+
+/* generate digest */
+#define MAX_DIGEST_SIZE                20
+
+CSSM_RETURN buGenDigest(
+       CSSM_ALGORITHMS         macAlg,                         // CSSM_ALGID_SHA1, etc. */
+       const CSSM_DATA         *ptext,
+       CSSM_DATA_PTR           digest)                         // mallocd and RETURNED 
+{
+#if 0 // NO MORE BSAFE
+       B_ALGORITHM_OBJ         alg = NULL;
+       int                             brtn;
+       CSSM_RETURN                     crtn;
+       B_INFO_TYPE                     infoType;
+       unsigned                        hashBytes;
+       
+       brtn = B_CreateAlgorithmObject(&alg);
+       if(brtn) {
+               return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject");
+       }
+       switch(macAlg) {
+               case CSSM_ALGID_SHA1:
+                       infoType = AI_SHA1;
+                       break;
+               case CSSM_ALGID_MD5:
+                       infoType = AI_MD5;
+                       break;
+               case CSSM_ALGID_MD2:
+                       infoType = AI_MD2;
+                       break;
+               default:
+                       printf("buGenDigest: alg not supported\n");
+                       return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
+       }
+       brtn = B_SetAlgorithmInfo(alg, infoType, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo");
+               goto abort;
+       }
+       brtn = B_DigestInit(alg, NULL, BSAFE_ALGORITHM_CHOOSER, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_DigestInit");
+               goto abort;
+       }
+       brtn = B_DigestUpdate(alg, ptext->Data, ptext->Length, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_DigestUpdate");
+               goto abort;
+       }
+       
+       /* prepare for digest, magically gleaned max size */
+       hashBytes = MAX_DIGEST_SIZE;
+       digest->Data = (uint8 *)CSSM_MALLOC(hashBytes);
+       digest->Length = hashBytes;
+       
+       brtn = B_DigestFinal(alg, digest->Data, &hashBytes, hashBytes, NULL);
+       if(brtn) {
+               crtn = buBsafeErrToCssm(brtn, "B_DigestFinal");
+               goto abort;
+       }
+       digest->Length = hashBytes;
+       crtn = CSSM_OK;
+abort:
+       B_DestroyAlgorithmObject(&alg);
+       return crtn;
+#else
+    return 0;
+#endif
+}
+
+/*
+ * Convert between BSAFE and CDSA private keys
+ */
+CSSM_RETURN buBsafePrivKeyToCdsa(
+       CSSM_ALGORITHMS         keyAlg,
+       uint32                          keySizeInBits,
+       BU_KEY                          bsafePrivKey,
+       CSSM_KEY_PTR            cdsaPrivKey)
+{
+#if 0 // NO MORE BSAFE
+       B_INFO_TYPE                     infoType;
+       ITEM                            *keyBlob;
+       int                                     brtn;
+       CSSM_KEYBLOB_FORMAT     format;
+       CSSM_KEYHEADER_PTR      hdr = &cdsaPrivKey->KeyHeader;
+       
+       /* what kind of info? */
+       switch(keyAlg) {
+               case CSSM_ALGID_RSA:
+                       infoType = KI_PKCS_RSAPrivateBER;
+                       format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
+                       break;
+               case CSSM_ALGID_DSA:
+                       infoType = KI_DSAPrivateBER;
+                       format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
+                       break;
+               default:
+                       printf("***buBsafePrivKeyToCdsa: bogus keyAlg\n");
+                       return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
+       }
+       
+       /* get the blob */
+       brtn = B_GetKeyInfo((POINTER *)&keyBlob,
+               (B_KEY_OBJ)bsafePrivKey,
+               infoType);
+       if(brtn) {
+               return buBsafeErrToCssm(brtn, "B_GetKeyInfo");
+       }
+       
+       /* copy blob to CDSA key */
+       cdsaPrivKey->KeyData.Data = (uint8 *)CSSM_MALLOC(keyBlob->len);
+       cdsaPrivKey->KeyData.Length = keyBlob->len;
+       memmove(cdsaPrivKey->KeyData.Data, keyBlob->data, keyBlob->len);
+       
+       /* set up CSSM key header */
+       memset(hdr, 0, sizeof(CSSM_KEYHEADER));
+       hdr->HeaderVersion = CSSM_KEYHEADER_VERSION;
+       hdr->BlobType = CSSM_KEYBLOB_RAW;
+       hdr->Format = format;
+       hdr->AlgorithmId = keyAlg;
+       hdr->KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
+       hdr->LogicalKeySizeInBits = keySizeInBits;
+       hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
+       hdr->KeyUsage = CSSM_KEYUSE_ANY;
+#endif
+       return CSSM_OK;
+}
+
+CSSM_RETURN buCdsaPrivKeyToBsafe(
+       CSSM_KEY_PTR            cdsaPrivKey,
+       BU_KEY                          *bsafePrivKey)
+{
+#if 0 // NO MORE BSAFE
+       int             brtn;
+       B_KEY_OBJ       privKey = NULL;
+       ITEM            keyBlob;
+       B_INFO_TYPE     infoType;
+       
+       /* what kind of info? */
+       switch(cdsaPrivKey->KeyHeader.AlgorithmId) {
+               case CSSM_ALGID_RSA:
+                       infoType = KI_PKCS_RSAPrivateBER;
+                       break;
+               case CSSM_ALGID_DSA:
+                       infoType = KI_DSAPrivateBER;
+                       break;
+               default:
+                       printf("***buCdsaPrivKeyToCssm: bogus keyAlg\n");
+                       return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED;
+       }
+       
+       /* create caller's key, assign blob to it */
+       brtn = B_CreateKeyObject(&privKey);
+       if(brtn) {
+               return buBsafeErrToCssm(brtn, "B_CreateKeyObject");
+       }
+       buCssmDataToItem(&cdsaPrivKey->KeyData, &keyBlob);
+       brtn = B_SetKeyInfo(privKey, infoType, (POINTER)&keyBlob);
+       if(brtn) {
+               return buBsafeErrToCssm(brtn, "B_SetKeyInfo");
+       }
+       *bsafePrivKey = privKey;
+#endif
+       return CSSM_OK;
+}
+