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; }
SCLError CCM_Encrypt(uint8_t *key, size_t keyLen, uint8_t *seq, size_t seqLen, const uint8_t *in, size_t inLen, uint8_t **outData, size_t *outSize, uint8_t *outTag, size_t tagSize) { SCLError err = kSCLError_NoErr; int status = CRYPT_OK; uint8_t bytes2Pad; uint8_t *buffer = NULL; size_t buffLen = 0; int IVlen = keyLen >>1; unsigned char T[32]; unsigned long tagLen = 0; unsigned long tag2Copy = tagSize; ValidateParam (tagSize <= sizeof(T)); /* calclulate Pad byte */ if(inLen < MIN_MSG_BLOCKSIZE) { bytes2Pad = MIN_MSG_BLOCKSIZE - inLen; } else { bytes2Pad = roundup(inLen, MSG_BLOCKSIZE) + MSG_BLOCKSIZE - inLen; }; buffLen = inLen + bytes2Pad; buffer = XMALLOC(buffLen); memcpy(buffer, in, inLen); memset(buffer+inLen, bytes2Pad, bytes2Pad); tagLen = sizeof(T); status = ccm_memory(find_cipher("aes"), key, IVlen , NULL, key+ IVlen, IVlen, seq, seqLen, buffer, buffLen, buffer, T, &tagLen , CCM_ENCRYPT); CKSTAT; *outData = buffer; *outSize = buffLen; memcpy(outTag, T, tag2Copy); done: if(status != CRYPT_OK) { if(buffer) { memset(buffer, buffLen, 0); XFREE(buffer); } err = sCrypt2SCLError(status); } return err; }
SCLError TestGCM() { SCLError err = kSCLError_NoErr; int status = CRYPT_OK; uint8_t key[32]; uint8_t* CT = NULL; size_t CTLen = 0; uint8_t* PT = NULL; size_t PTLen = 0; unsigned char T[32]; unsigned long tagLen = 0; int i; register_cipher (&aes_desc); printf("\nTesting GCM encoding \n\n"); for(i = 0; Msgs[i] != NULL; i++) { unsigned long msgLen; uint8_t seqNum[6]; sprng_read(key,sizeof(key),NULL); msgLen = strlen(Msgs[i]); // sprintf(seqNum, "%05d ", i); // printf("\n%s %3d |%s|\n\n", seqNum, (int)msgLen, Msgs[i]); err = GCM_Encrypt( key, sizeof(key), seqNum, sizeof(seqNum), Msgs[i], msgLen, &CT, &CTLen, T, &tagLen); CKERR; // Error test // seqNum[0]= seqNum[0]+1; // T[0]= T[0]+1; err = GCM_Decrypt( key, sizeof(key), seqNum, sizeof(seqNum), CT, CTLen, T, tagLen, &PT, &PTLen); CKERR; // dumpHex(CT, CTLen, 0); // printf("Tag %d: ", (int)tagLen); dumpHex8(T); dumpHex8(T+8); // printf("\n"); if(msgLen != PTLen) { printf("ERROR GCM Decrypt: Expecting %d bytes, got %d\n", (int)msgLen, (int)PTLen ); RETERR(kSCLError_SelfTestFailed); } if( compareResults( Msgs[i], PT, msgLen , kResultFormat_Byte, "GCM Decrypt") != CRYPT_OK) { RETERR(kSCLError_SelfTestFailed); } // printf(" %5d |%.*s|\n\n", (int)PTLen,(int)PTLen, PT ); if(CT) { memset(CT, CTLen, 0); XFREE(CT); CT = NULL; } if(PT) { memset(PT,PTLen, 0); XFREE(PT); PT = NULL; } } done: if(status != CRYPT_OK) err = sCrypt2SCLError(status); if(CT) { memset(CT, CTLen, 0); XFREE(CT); CT = NULL; } if(PT) { memset(PT,PTLen, 0); XFREE(PT); PT = NULL; } return err; }