]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/cspxutils/utilLib/ssleayUtils.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / utilLib / ssleayUtils.cpp
diff --git a/SecurityTests/cspxutils/utilLib/ssleayUtils.cpp b/SecurityTests/cspxutils/utilLib/ssleayUtils.cpp
new file mode 100644 (file)
index 0000000..5b430b2
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * ssleayUtils.c - common routines for CDSA/openssl compatibility testing
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <openssl/blowfish.h>
+#include <openssl/cast.h>
+#include <openssl/evp.h>
+#include "ssleayUtils.h"
+#include <Security/cssmerr.h>
+#include "common.h"
+
+/*
+ * Caller sees EAY_KEY, we see a pointer to this.
+ */
+typedef struct {
+       CSSM_ALGORITHMS alg;
+       union {
+               BF_KEY                          bf;             // blowfish
+               CAST_KEY                        cast;
+       } key;
+} EayKeyPriv;
+
+/*
+ * Create a symmetric key.
+ */
+CSSM_RETURN  eayGenSymKey(
+       CSSM_ALGORITHMS alg,
+       CSSM_BOOL               forEncr,
+       const CSSM_DATA *keyData,
+       EAY_KEY                 *key)                   // RETURNED
+{
+       EayKeyPriv *ekp = (EayKeyPriv *)malloc(sizeof(EayKeyPriv));
+       memset(ekp, 0, sizeof(*ekp));
+       switch(alg) {
+               case CSSM_ALGID_BLOWFISH:
+                       BF_set_key(&ekp->key.bf, keyData->Length, keyData->Data);
+                       break;
+               case CSSM_ALGID_CAST:           // cast128 only
+                       CAST_set_key(&ekp->key.cast, keyData->Length, keyData->Data);
+                       break;
+               default:
+                       printf("***eayGenSymKey: bad alg\n");
+                       return -1;
+       }
+       ekp->alg = alg;
+       *key = (EAY_KEY)ekp;
+       return CSSM_OK;
+}
+
+/*
+ * Free a key created in eayGenSymKey
+ */
+CSSM_RETURN eayFreeKey(
+       EAY_KEY                 key)
+{
+       memset(key, 0, sizeof(EayKeyPriv));
+       free(key);
+       return CSSM_OK;
+}
+
+/*
+ * encrypt/decrypt
+ */
+CSSM_RETURN eayEncryptDecrypt(
+       EAY_KEY                         key,
+       CSSM_BOOL                       forEncrypt,
+       CSSM_ALGORITHMS         encrAlg,
+       CSSM_ENCRYPT_MODE       mode,                           // CSSM_ALGMODE_CBC ONLY!
+       const CSSM_DATA         *iv,                            //ĂŠoptional per mode
+       const CSSM_DATA         *inData,
+       CSSM_DATA_PTR           outData)                        // CSSM_MALLOCd and RETURNED
+{
+       EayKeyPriv *ekp = (EayKeyPriv *)key;
+       if((mode != CSSM_ALGMODE_CBC_IV8) && (mode != CSSM_ALGMODE_ECB)) {
+               printf("***eayEncryptDecrypt only does CBC_IV8, ECB\n");
+               return -1;
+       }
+       
+       bool cbc = (mode == CSSM_ALGMODE_ECB) ? false : true;
+       
+       outData->Data = (uint8 *)CSSM_MALLOC(inData->Length);
+       outData->Length = inData->Length;
+       
+       /* BF_cbc_encrypt actually writes to IV */
+       CSSM_DATA ivc = {0, NULL};
+       if(cbc) {
+               ivc.Data = (uint8 *)malloc(iv->Length);
+               ivc.Length = iv->Length;
+               memmove(ivc.Data, iv->Data, ivc.Length);
+       }
+       switch(encrAlg) {
+               case CSSM_ALGID_BLOWFISH:
+                       if(cbc) {
+                               BF_cbc_encrypt(inData->Data,
+                                       outData->Data,
+                                       inData->Length,
+                                       &ekp->key.bf,
+                                       ivc.Data,
+                                       forEncrypt ? BF_ENCRYPT : BF_DECRYPT);
+                       }
+                       else {
+                               CSSM_DATA intext = *inData;
+                               CSSM_DATA outtext = *outData;
+                               while(intext.Length) {
+                                       BF_ecb_encrypt(intext.Data,
+                                               outtext.Data,
+                                               &ekp->key.bf,
+                                               forEncrypt ? BF_ENCRYPT : BF_DECRYPT);
+                                       intext.Data   += 8;
+                                       outtext.Data  += 8;
+                                       intext.Length -= 8;
+                               }
+                       }
+                       break;
+               case CSSM_ALGID_CAST:           // cast128 only
+                       CAST_cbc_encrypt(inData->Data,
+                               outData->Data,
+                               inData->Length,
+                               &ekp->key.cast,
+                               ivc.Data,
+                               forEncrypt ? CAST_ENCRYPT : CAST_DECRYPT);
+                       break;
+               default:
+                       printf("***eayEncryptDecrypt: bad alg\n");
+                       return -1;
+       }
+       if(ivc.Data) {
+               free(ivc.Data);
+       }
+       return CSSM_OK;
+}
+
+/*** EVP-based encrypt/decrypt ***/
+
+int evpEncryptDecrypt(
+       CSSM_ALGORITHMS         alg,                            // AES 128 only for now 
+       CSSM_BOOL                       forEncr,
+       const CSSM_DATA         *keyData,                       // may be larger than the key size we use
+       unsigned                        keyLengthInBits,
+       CSSM_ENCRYPT_MODE       mode,                           // CSSM_ALGMODE_CBC_IV8, ECB, always padding
+       const CSSM_DATA         *iv,                            // optional per mode
+       const CSSM_DATA         *inData,
+       CSSM_DATA_PTR           outData)                        // CSSM_MALLOCd and RETURNED
+{
+       EVP_CIPHER_CTX ctx;
+       const EVP_CIPHER *cipher;
+       unsigned blockSize;
+       unsigned outLen = inData->Length;
+       bool noPad = false;
+       
+       switch(alg) {
+               case CSSM_ALGID_AES:
+                       switch(mode) {
+                               case CSSM_ALGMODE_CBCPadIV8:
+                                       switch(keyLengthInBits) {
+                                               case 128:
+                                                       cipher = EVP_aes_128_cbc();
+                                                       break;
+                                               case 192:
+                                                       cipher = EVP_aes_192_cbc();
+                                                       break;
+                                               case 256:
+                                                       cipher = EVP_aes_256_cbc();
+                                                       break;
+                                               default:
+                                                       printf("***Bad AES key length (%u)\n", keyLengthInBits);
+                                                       return -1;
+                                       }
+                                       break;
+                               case CSSM_ALGMODE_ECB:
+                                       switch(keyLengthInBits) {
+                                               case 128:
+                                                       cipher = EVP_aes_128_ecb();
+                                                       break;
+                                               case 192:
+                                                       cipher = EVP_aes_192_ecb();
+                                                       break;
+                                               case 256:
+                                                       cipher = EVP_aes_256_ecb();
+                                                       break;
+                                               default:
+                                                       printf("***Bad AES key length (%u)\n", keyLengthInBits);
+                                                       return -1;
+                                       }
+                                       noPad = true;
+                                       break;
+                               default:
+                                       printf("***evpEncryptDecrypt only does CBC and ECB for now\n");
+                                       return -1;
+                       }
+                       blockSize = 16;
+                       break;
+               case CSSM_ALGID_DES:
+                       switch(mode) {
+                               case CSSM_ALGMODE_CBCPadIV8:
+                                       cipher = EVP_des_cbc();
+                                       break;
+                               case CSSM_ALGMODE_ECB:
+                                       cipher = EVP_des_ecb();
+                                       noPad = true;
+                                       break;
+                               default:
+                                       printf("***evpEncryptDecrypt only does CBC and ECB for now\n");
+                                       return -1;
+                       }
+                       blockSize = 8;
+                       break;
+               default:
+                       printf("***evpEncryptDecrypt only does DES and AES 128 for now\n");
+                       return -1;
+       }
+       outLen += blockSize;
+       unsigned char *outp = (uint8 *)CSSM_MALLOC(outLen);
+       int outl = outLen;
+       outData->Data = outp;
+       
+       if(forEncr) {
+               int rtn = EVP_EncryptInit(&ctx, cipher, keyData->Data, iv ? iv->Data : NULL);
+               if(!rtn) {
+                       printf("EVP_EncryptInit error\n");
+                       return -1;
+               }
+               if(noPad) {
+                       EVP_CIPHER_CTX_set_padding(&ctx, 0);
+               }
+               if(!EVP_EncryptUpdate(&ctx, outp, &outl, inData->Data, inData->Length)) {
+                       printf("EVP_EncryptUpdate error\n");
+                       return -1;
+               }
+       }
+       else {
+               int rtn = EVP_DecryptInit(&ctx, cipher, keyData->Data, iv ? iv->Data : NULL);
+               if(!rtn) {
+                       printf("EVP_DecryptInit error\n");
+                       return -1;
+               }
+               if(noPad) {
+                       EVP_CIPHER_CTX_set_padding(&ctx, 0);
+               }
+               
+               if(!EVP_DecryptUpdate(&ctx, outp, &outl, inData->Data, inData->Length)) {
+                       printf("EVP_DecryptUpdate error\n");
+                       return -1;
+               }
+       }
+       outData->Length = outl;
+       outp += outl;
+       outl = outLen - outl;
+       if(forEncr) {
+               if(!EVP_EncryptFinal(&ctx, outp, &outl)) {
+                       printf("EVP_EncryptFinal error\n");
+                       return -1;
+               }
+       }
+       else {
+               if(!EVP_DecryptFinal(&ctx, outp, &outl)) {
+                       printf("EVP_DecryptFinal error\n");
+                       return -1;
+               }
+       }
+       outData->Length += outl;
+       return 0;
+}