SCLError CCM_Decrypt(uint8_t *key, size_t keyLen, uint8_t *seq, size_t seqLen, uint8_t *in, size_t inLen, uint8_t *tag, size_t tagSize, uint8_t **outData, size_t *outSize) { SCLError err = kSCLError_NoErr; int status = CRYPT_OK; uint8_t *buffer = NULL; size_t buffLen = inLen; int IVlen = keyLen >>1; uint8_t bytes2Pad = 0; unsigned char T[32]; unsigned long tagLen = sizeof(T); buffer = XMALLOC(buffLen); status = ccm_memory(find_cipher("aes"), key, IVlen , NULL, key+ IVlen, IVlen, seq, seqLen, buffer, buffLen, in, T, &tagLen , CCM_DECRYPT);CKSTAT; // This will only compare as many bytes of the tag as you specify in tagSize // we need to be careful with CCM to not leak key information, an easy way to do // that is to only export half the hash. if((memcmp(T,tag,tagSize) != 0)) RETERR(kSCLError_CorruptData); bytes2Pad = *(buffer+buffLen-1); *outData = buffer; *outSize = buffLen- bytes2Pad; done: if(status != CRYPT_OK || err != kSCLError_NoErr) { if(buffer) { memset(buffer, buffLen, 0); XFREE(buffer); } err = IsSCLError(err)?err:sCrypt2SCLError(status); } return err; }
SCLError GCM_Decrypt(uint8_t *key, size_t keyLen, uint8_t *seq, size_t seqLen, uint8_t *in, size_t inLen, uint8_t *tag, size_t tagSize, uint8_t **outData, size_t *outSize) { SCLError err = kSCLError_NoErr; int status = CRYPT_OK; uint8_t *buffer = NULL; size_t buffLen = inLen; int IVlen = keyLen >>1; uint8_t bytes2Pad = 0; unsigned char T[32]; unsigned long tagLen = sizeof(T); buffer = XMALLOC(buffLen); status = gcm_memory(find_cipher("aes"), key, IVlen , key+ IVlen, IVlen, seq, seqLen, buffer, buffLen, in, T, &tagLen , GCM_DECRYPT);CKSTAT; if( tagLen != tagSize || (memcmp(T,tag,tagLen) != 0)) RETERR(kSCLError_CorruptData); bytes2Pad = *(buffer+buffLen-1); *outData = buffer; *outSize = buffLen- bytes2Pad; done: if(status != CRYPT_OK || err != kSCLError_NoErr) { if(buffer) { memset(buffer, buffLen, 0); XFREE(buffer); } err = IsSCLError(err)?err:sCrypt2SCLError(status); } return err; }
static SCLError sTestECC(int keySize) { #define PTsize 32 SCLError err = kSCLError_NoErr; int i; uint8_t PT[PTsize]; uint8_t CT[256]; size_t CTlen = 0; uint8_t DT[PTsize]; size_t DTlen = 0; uint8_t pubKey[256]; size_t pubKeyLen = 0; uint8_t privKey[256]; size_t privKeyLen = 0; bool isPrivate = false; size_t importKeySize = 0; bool isANSIx963 = false; // uint8_t tempBuf[256]; // unsigned long tempLen; OPTESTLogInfo("\tECC-%d \n", keySize); ECC_ContextRef ecc = kInvalidECC_ContextRef; ECC_ContextRef eccPub = kInvalidECC_ContextRef; // fill PT for(i = 0; i< PTsize; i++) PT[i]= i; err = ECC_Init(&ecc); OPTESTLogVerbose("\t\tGenerate Pub Key (%ld bytes)\n", pubKeyLen); err = ECC_Generate(ecc, keySize); CKERR; err = ECC_Export_ANSI_X963( ecc, pubKey, sizeof(pubKey), &pubKeyLen);CKERR; OPTESTLogVerbose("\t\tExport Public Key (%ld bytes)\n", pubKeyLen); dumpHex(IF_LOG_DEBUG, pubKey, (int)pubKeyLen, 0); err = ECC_Import_Info( pubKey, pubKeyLen, &isPrivate, &isANSIx963, &importKeySize );CKERR; OPTESTLogVerbose("\t\t\t%d bit %s%s key\n", (int)importKeySize , isANSIx963 ?"ANSI x9.63 ":"", isPrivate ?"private":"public"); err = ECC_Export(ecc, true, privKey, sizeof(privKey), &privKeyLen);CKERR; OPTESTLogVerbose("\t\tExport Private Key (%ld bytes)\n", privKeyLen); dumpHex(IF_LOG_DEBUG, privKey, (int)privKeyLen, 0); err = ECC_Import_Info( privKey, privKeyLen, &isPrivate, &isANSIx963, &importKeySize );CKERR; OPTESTLogVerbose("\t\t\t%d bit %s%s key\n", (int)importKeySize , isANSIx963 ?"ANSI x9.63 ":"", isPrivate ?"private":"public"); // delete keys if(ECC_ContextRefIsValid(ecc) ) ECC_Free(ecc ); ecc = kInvalidECC_ContextRef; err = ECC_Init(&eccPub); err = ECC_Import_ANSI_X963( eccPub, pubKey, pubKeyLen);CKERR; importKeySize = 0; err = ECC_KeySize(eccPub, &importKeySize); OPTESTLogVerbose("\t\tImported %d bit public key\n", (int)importKeySize ); err = ECC_Encrypt(eccPub, PT, sizeof(PT), CT, sizeof(CT), &CTlen);CKERR; OPTESTLogVerbose("\t\tEncrypt message: (%ld bytes)\n", CTlen); dumpHex(IF_LOG_DEBUG, CT, (int)CTlen, 0); err = ECC_Init(&ecc); err = ECC_Import(ecc, privKey, privKeyLen);CKERR; err = ECC_KeySize(ecc, &importKeySize); OPTESTLogVerbose("\t\tImported %d bit private key\n", (int)importKeySize ); err = ECC_Decrypt(ecc, CT, CTlen, DT, sizeof(DT), &DTlen); CKERR; /* check against know-answer */ err= compareResults( DT, PT, PTsize , kResultFormat_Byte, "ECC Decrypt"); CKERR; OPTESTLogVerbose("\t\tDecrypted OK\n"); dumpHex(IF_LOG_DEBUG, DT, (int)DTlen, 0); err = ECC_Sign(ecc, PT, sizeof(PT), CT, sizeof(CT), &CTlen);CKERR; OPTESTLogVerbose("\t\tSigned message (%ld bytes)\n", CTlen); dumpHex(IF_LOG_DEBUG, CT, (int)CTlen, 0); err = ECC_Verify(ecc, CT, CTlen, PT, sizeof(PT)); OPTESTLogVerbose("\t\tVerify = %s\n", IsSCLError(err)?"fail":"pass"); PT[3]= 9; err = ECC_Verify(ecc, CT, CTlen, PT, sizeof(PT)); OPTESTLogVerbose("\t\tVerify bad packet = %s\n", IsSCLError(err)?"fail":"pass"); if(err == kSCLError_BadIntegrity) err = kSCLError_NoErr; OPTESTLogVerbose("\n"); done: if(ECC_ContextRefIsValid(ecc) ) ECC_Free(ecc ); if(ECC_ContextRefIsValid(eccPub)) ECC_Free(eccPub); return err; }