int qcrypto_cipher_encrypt(QCryptoCipher *cipher, const void *in, void *out, size_t len, Error **errp) { QCryptoCipherNettle *ctx = cipher->opaque; if (len % ctx->blocksize) { error_setg(errp, "Length %zu must be a multiple of block size %zu", len, ctx->blocksize); return -1; } switch (cipher->mode) { case QCRYPTO_CIPHER_MODE_ECB: ctx->alg_encrypt(ctx->ctx_encrypt, len, out, in); break; case QCRYPTO_CIPHER_MODE_CBC: cbc_encrypt(ctx->ctx_encrypt, ctx->alg_encrypt, ctx->blocksize, ctx->iv, len, out, in); break; default: error_setg(errp, "Unsupported cipher algorithm %d", cipher->alg); return -1; } return 0; }
void test_cipher_cbc(const struct nettle_cipher *cipher, const struct tstring *key, const struct tstring *cleartext, const struct tstring *ciphertext, const struct tstring *iiv) { void *ctx = xalloc(cipher->context_size); uint8_t *data; uint8_t *iv = xalloc(cipher->block_size); unsigned length; ASSERT (cleartext->length == ciphertext->length); length = cleartext->length; ASSERT (iiv->length == cipher->block_size); data = xalloc(length); cipher->set_encrypt_key(ctx, key->length, key->data); memcpy(iv, iiv->data, cipher->block_size); cbc_encrypt(ctx, cipher->encrypt, cipher->block_size, iv, length, data, cleartext->data); if (!MEMEQ(length, data, ciphertext->data)) { fprintf(stderr, "CBC encrypt failed:\nInput:"); tstring_print_hex(cleartext); fprintf(stderr, "\nOutput: "); print_hex(length, data); fprintf(stderr, "\nExpected:"); tstring_print_hex(ciphertext); fprintf(stderr, "\n"); FAIL(); } cipher->set_decrypt_key(ctx, key->length, key->data); memcpy(iv, iiv->data, cipher->block_size); cbc_decrypt(ctx, cipher->decrypt, cipher->block_size, iv, length, data, data); if (!MEMEQ(length, data, cleartext->data)) { fprintf(stderr, "CBC decrypt failed:\nInput:"); tstring_print_hex(ciphertext); fprintf(stderr, "\nOutput: "); print_hex(length, data); fprintf(stderr, "\nExpected:"); tstring_print_hex(cleartext); fprintf(stderr, "\n"); FAIL(); } free(ctx); free(data); free(iv); }
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits){ calc_size_n_pad(size_p); byte plain_p[get_size()]; padPlaintext(plain,plain_p); int blocks = get_size() / N_BLOCK; set_key (key, bits) ; cbc_encrypt (plain_p, cipher, blocks); }
static int myaes_encrypt(void *_ctx, const void *src, size_t src_size, void *dst, size_t dst_size) { struct myaes_ctx *ctx = _ctx; used++; cbc_encrypt(&ctx->aes, (nettle_cipher_func*)aes_encrypt, 16, ctx->iv, src_size, dst, src); return 0; }
static int sqlcipher_ltc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) { int rc, cipher_idx, hash_idx; symmetric_CBC cbc; if((cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx))) == -1) return SQLITE_ERROR; if((rc = cbc_start(cipher_idx, iv, key, key_sz, 0, &cbc)) != CRYPT_OK) return SQLITE_ERROR; rc = mode == 1 ? cbc_encrypt(in, out, in_sz, &cbc) : cbc_decrypt(in, out, in_sz, &cbc); if(rc != CRYPT_OK) return SQLITE_ERROR; cbc_done(&cbc); return SQLITE_OK; }
static int cbc_test_generic(DrewLoader *ldr, const char *name, const struct test *testdata, size_t ntests) { int id, result = 0; const drew_block_functbl_t *functbl; drew_block_t algo; drew_mode_t c; const void *tmp; uint8_t buf[128]; id = drew_loader_lookup_by_name(ldr, name, 0, -1); if (id < 0) return id; drew_loader_get_functbl(ldr, id, &tmp); functbl = tmp; functbl->init(&algo, 0, ldr, NULL); for (size_t i = 0; i < ntests; i++) { memset(buf, 0, sizeof(buf)); result <<= 1; cbc_init(&c, 0, ldr, NULL); algo.functbl->init(&algo, 0, ldr, NULL); algo.functbl->setkey(&algo, testdata[i].key, testdata[i].keysz, DREW_BLOCK_MODE_ENCRYPT); cbc_setblock(&c, &algo); cbc_setiv(&c, testdata[i].iv, testdata[i].ivsz); cbc_encrypt(&c, buf, testdata[i].input, MIN(sizeof(buf), testdata[i].datasz)); result |= !!memcmp(buf, testdata[i].output, testdata[i].datasz); cbc_fini(&c, 0); algo.functbl->fini(&algo, 0); cbc_init(&c, 0, ldr, NULL); algo.functbl->init(&algo, 0, ldr, NULL); algo.functbl->setkey(&algo, testdata[i].key, testdata[i].keysz, DREW_BLOCK_MODE_DECRYPT); cbc_setblock(&c, &algo); cbc_setiv(&c, testdata[i].iv, testdata[i].ivsz); cbc_decrypt(&c, buf, testdata[i].output, MIN(sizeof(buf), testdata[i].datasz)); result |= !!memcmp(buf, testdata[i].input, testdata[i].datasz); cbc_fini(&c, 0); algo.functbl->fini(&algo, 0); } return result; }
int verify(char *data, size_t len, error *err) { cbc_decrypt(data, data, len, key, key); int valid = 1; for (size_t i = 0; i < len; ++i) { if (data[i] < 0) { valid = 0; err->msg[0] = '\0'; strcpy(err->msg, "Invalid message: "); memcpy(err->msg + strlen(err->msg), data, len); // overrun break; } } // Undo changes. cbc_encrypt(data, data, len, key, key); return valid; }
//TODO: NO COPY ! void sendDataPkt(uint8_t *data, int dataLen){ #if DEBUG printf("[!] sendDataPkt %d\n", pkt_number); #endif //Replace pkt number... KDNET_POST_HEADER* tmp = (KDNET_POST_HEADER*)data; tmp->PacketNumber = __builtin_bswap32(pkt_number++); int i; //Add header KDNET_PACKET_HEADER finalPkt; //TODO: no static ! finalPkt.Signature = 0x4742444d;//TODO: define ! finalPkt.ProtocolVersion = 0x02; finalPkt.Canal = 0x0; //TODO: define ! for(i=0; i<dataLen; i++){ finalPkt.CipheredData[i] = data[i]; } #if DEBUG printf("----------SENT CLEAR DATA WITHOUT HMAC---------\n"); printHexData((uint8_t*)&finalPkt, dataLen+6); printf("-----------------------------------------------\n"); #endif //Compute checksum whith hmachKey uint8_t tmpHMACSHA256[32]; hmachSHA256((uint8_t*)&finalPkt, dataLen+6, hmacKey, tmpHMACSHA256); #if DEBUG printf("------------------HMAC-------------------------\n"); printHexData(tmpHMACSHA256, 32); printf("-----------------------------------------------\n"); #endif //Ciphered with KEY:dataW IV:tmpHMACSHA256 uint8_t* tmpData = cbc_encrypt(data, dataLen, dataW, tmpHMACSHA256); //Replace to cleartext with the ciphertext for(i=0; i<dataLen; i++){ finalPkt.CipheredData[i] = tmpData[i]; } //Add IV/HMAC for(i=0; i<16; i++){ finalPkt.CipheredData[dataLen+i] = tmpHMACSHA256[i]; } //Send on socket ! sendto(socket_fd, &finalPkt, dataLen+6+16, MSG_DONTWAIT, (struct sockaddr *)&sa,sizeof(sa)); }
void presentencrypt(char *str, uint8_t *retstr) { pcg32_random_t rng; pcg32_srandom_r(&rng, time(NULL) ^ (intptr_t)&printf, (intptr_t)&rounds); uint32_t rang = pcg32_random_r(&rng); memcpy(iv,&rang,sizeof(iv)); uint8_t newMessage[200]; //pad the message string and turn into bytearray padStr(str,newMessage); cbc_encrypt((uint8_t*)theKey,iv,newMessage,lenmsg); memcpy(retstr,newMessage,sizeof(newMessage)); printf("sizeof(newMessage) %d\n", sizeof(newMessage)); }
C4Err CBC_Encrypt(CBC_ContextRef ctx, const void * in, size_t bytesIn, void * out ) { C4Err err = kC4Err_NoErr; int status = CRYPT_OK; validateCBCContext(ctx); status = cbc_encrypt(in, out, bytesIn, &ctx->state); err = sCrypt2C4Err(status); return (err); }
char *encode_user_data(char *user_data, size_t *n) { char *prefix = "comment1=cooking%20MCs;userdata="; char *suffix = ";comment2=%20like%20a%20pound%20of%20bacon"; *n = strlen(user_data) + strlen(prefix) + strlen(suffix) + 100; char *encoded = calloc(*n, 1); strcat(encoded, prefix); char *q = encoded + strlen(encoded); for (char *p = user_data; *p; ++p) { // Get rid of characters we don't like. if (*p != '=' && *p != ';') { *q++ = *p; } } strcat(q, suffix); *n = pkcs7(encoded, *n, 16); cbc_encrypt(encoded, encoded, *n, key, key); return encoded; }
static int myaes_encrypt(void *_ctx, const void *src, size_t src_size, void *dst, size_t dst_size) { struct myaes_ctx *ctx = _ctx; #if 0 /* this is under the control of the caller */ if (((unsigned long)src)%16 != 0) { fail("encrypt: source is not 16-byte aligned: %lu\n", ((unsigned long)src)%16); } #endif if (((unsigned long)dst)%16 != 0) { fail("encrypt: dest is not 16-byte aligned: %lu\n", ((unsigned long)dst)%16); } cbc_encrypt(&ctx->aes, (nettle_cipher_func*)aes_encrypt, 16, ctx->iv, src_size, dst, src); return 0; }
void CAESModule::encrypt(Tools::CSecureMemory &rCypherText, Tools::CSecureMemory const &rPlainText) const { FASSERT(mKey.getSize() == gKeySize); Tools::CSecureMemory IV; getRandomIV(IV); Tools::CSecureMemory PaddedPlainText; getPadding(PaddedPlainText, rPlainText); int ErrorCode; rCypherText.allocate(PaddedPlainText.getSize()+IV.getSize()); std::memcpy(&rCypherText[0], &IV[0], IV.getSize()); int const Cipher = find_cipher("rijndael"); FASSERT(Cipher != -1); symmetric_CBC CBCMode; ErrorCode = cbc_start(Cipher, &IV[0], &mKey[0], static_cast<unsigned long>(mKey.getSize()), 0, &CBCMode); if (ErrorCode != CRYPT_OK) { throw ExInternalError(std::string("Cannot setup AES cipher: ") + std::string(error_to_string(ErrorCode))); } ErrorCode = cbc_encrypt(&PaddedPlainText[0], &rCypherText[IV.getSize()], static_cast<unsigned long>(PaddedPlainText.getSize()), &CBCMode); if (ErrorCode != CRYPT_OK) { throw ExInternalError(std::string("Error during encryption: ") + std::string(error_to_string(ErrorCode))); } ErrorCode = cbc_done(&CBCMode); if (ErrorCode != CRYPT_OK) { throw ExInternalError(std::string("Error when closing encryption stream: ") + std::string(error_to_string(ErrorCode))); } return; }
void A_send_msg(char *msg, dh_key key_a, mpz_t *B, char *out, char iv[16]) { char key[16]; mpz_t s; char *s_str; SHA1Context ctx; // Random IV for (size_t i = 0; i < 16; ++i) { iv[i] = randn(256) - 128; } // Get the session key and hash it to make the encryption key dh_session_key(key_a, &s, B); s_str = mpz_get_str(NULL, 16, s); assert(shaSuccess == SHA1Reset(&ctx)); assert(shaSuccess == SHA1Input(&ctx, (uint8_t *)s_str, strlen(s_str))); assert(shaSuccess == SHA1Result(&ctx, (uint8_t *)out)); memcpy(key, out, 16); // Encrypt cbc_encrypt(msg, out, strlen(msg), iv, key); free(s_str); }
/*++ EncryptCBC EncryptCFB EncryptCTR EncryptECB EncryptOFB Encrypts data in the specified cipher mode and algorithm. Arguments: cipher - Index of the desired cipher. rounds - Number of rounds. counterMode - The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN). iv - The initial vector, must be the length of one block. key - The secret key. keyLength - Length of the secret key, in bytes. data - Plain text (data to encrypt). dataLength - Length of plain text, in bytes. dest - Buffer to receive cipher text (encrypted data). Return Value: A LibTomCrypt status code; CRYPT_OK will be returned if successful. --*/ static int EncryptCBC( int cipher, int rounds, int counterMode, unsigned char *iv, unsigned char *key, unsigned long keyLength, unsigned char *data, unsigned long dataLength, unsigned char *dest ) { int status; symmetric_CBC state; status = cbc_start(cipher, iv, key, keyLength, rounds, &state); if (status == CRYPT_OK) { status = cbc_encrypt(data, dest, dataLength, &state); cbc_done(&state); } return status; }
// ========================================================================= // Encryption function // Note: CyphertextLength must be set to the size of the CyphertextData buffer on // entry; on exit, this will be set to the size of the buffer used. NTSTATUS ImpCypherEncryptSectorData( IN GUID* CypherGUID, IN LARGE_INTEGER SectorID, // Indexed from zero IN int SectorSize, // In bytes IN int KeyLength, // In bits IN FREEOTFEBYTE* Key, IN char* KeyASCII, // ASCII representation of "Key" IN int IVLength, // In bits IN FREEOTFEBYTE* IV, IN int PlaintextLength, // In bytes IN FREEOTFEBYTE* PlaintextData, OUT FREEOTFEBYTE* CyphertextData ) { NTSTATUS status = STATUS_SUCCESS; // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL char ltcNullIV[FREEOTFE_MAX_CYPHER_BLOCKSIZE]; int cipher; symmetric_CBC *cbc; int errnum; DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherEncryptData\n"))); if (!( (IsEqualGUID(&CIPHER_GUID_CAST5, CypherGUID)) )) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unsupported cipher GUID passed in.\n"))); status = STATUS_INVALID_PARAMETER; } // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL if ( (IVLength == 0) || (IV == NULL) ) { FREEOTFE_MEMZERO(<cNullIV, sizeof(ltcNullIV)); IV = (char*)<cNullIV; } cbc = FREEOTFE_MEMALLOC(sizeof(symmetric_CBC)); FREEOTFE_MEMZERO(cbc, sizeof(symmetric_CBC)); if NT_SUCCESS(status) { status = InitLTCCypher(&cipher); } if NT_SUCCESS(status) { // Start a CBC session if ((errnum = cbc_start( cipher, IV, Key, (KeyLength/8), 0, cbc )) != CRYPT_OK) { status = STATUS_UNSUCCESSFUL; DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start CBC session (errnum: %d)\n"), errnum)); } else { if ((errnum = cbc_encrypt( PlaintextData, CyphertextData, PlaintextLength, cbc )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt/decrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } cbc_done(cbc); } } SecZeroMemory(cbc, sizeof(symmetric_CBC)); FREEOTFE_FREE(cbc); DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("ImpCypherEncryptData\n"))); return status; }
/*! * \brief Main application function. \n * -> Initialize clock \n * -> Initialize USART for print functions \n * -> Initialize AES to generate Key schedule for AES-128 \n * -> Based on the AES mode enabled in conf_example.h file, \n * execute encryption and decryption of a message and \n * compare them against input data to check its functionality. \n * -> The decrypted message can be viewed on the COM port terminal \n */ int main(void) { /* * Initialize the System clock * Note: Clock should be configured in conf_clock.h */ system_init(); /* Configure EDBG SERCOM UART to print messages */ configure_usart(); /* Generate key schedule for AES-128 from the Cipher Key */ aes_init(key_vectors); /* Print status messages */ printf("AES key generated successfully!..\r\n"); /* Print Input message for user */ printf("\n The message to be encrypted is:\r\n"); printf("\n %s \r\n",pText); /* * Perform ECB, CFB, OFB, CTR and CBC Encryption and Decryption * based on the mode enabled in conf_example.h. User can choose * the mode that he wants to evaluate. By default, all modes are * enabled. * The decrypted message is printed to EDBG virtual COM port. * If the decrypted message is same as the input plain text, * it ensures the working of each mode. */ #if (AES_ECB == true) //Perform ECB Encryption ecb_encrypt( pText, cText, sizeof(pText) ); for (volatile int i = 0; i < 1000; i++); //Perform ECB Decryption ecb_decrypt( cText, pText1, sizeof(cText)); //Print decrypted message printf("\n Decrypted message using AES-ECB mode : \r\n"); printf("\n %s \r\n",pText1); #endif #if (AES_CFB == true) //Perform CFB Encryption cfb_encrypt(pText, cText, init_vector, CFB_MODE_128, sizeof(pText)); for (volatile int i = 0; i < 1000; i++); //Perform CFB Decryption cfb_decrypt(cText, pText1, init_vector, CFB_MODE_128, sizeof(cText)); //Print decrypted message printf("\n Decrypted message using AES-CFB mode : \r\n"); printf("\n %s \r\n",pText1); #endif #if (AES_OFB == true) //Perform OFB Encryption ofb_encrypt(pText, cText, init_vector, sizeof(pText)); for (volatile int i = 0; i < 1000; i++); //Perform OFB Decryption ofb_encrypt(cText, pText1, init_vector, sizeof(cText)); //Print decrytped message printf("\n Decrypted message using AES-OFB mode : \r\n"); printf("\n %s \r\n",pText1); #endif #if (AES_CTR == true) /* Initialize Counter block with initialization vector, * nonce and counter value */ ctr_blk_t counter_vector = { .i_vector = AES_CTR_IVECTOR, .nonce = AES_CTR_NONCE, .counter = AES_CTR_COUNTER }; //Perform CTR Encryption ctr_encrypt_decrypt(pText, cText, &counter_vector, sizeof(pText)); //Send Counter block value to decryptor for (volatile int i = 0; i < 1000; i++); counter_vector.i_vector = AES_CTR_IVECTOR; counter_vector.nonce = AES_CTR_NONCE; counter_vector.counter = AES_CTR_COUNTER; //Perform CTR Decryption ctr_encrypt_decrypt(cText, pText1, &counter_vector, sizeof(pText1)); //Print decrypted message printf("\n Decrypted message using AES-CTR mode : \r\n"); printf("\n %s \r\n",pText1); #endif /*! \warning CBC mode is done at the last as it process input plain text * during encryption and so the plain text value is not retained. * For testing purpose, to preserve the input plan text for testing with * other modes, this mode is added at the last. */ #if (AES_CBC == true) //Perform CBC Encryption cbc_encrypt(pText, cText, init_vector, sizeof(pText)); for (volatile int i = 0; i < 1000; i++); //Perform CBC Decryption cbc_decrypt(cText, pText1, init_vector, sizeof(cText)); //Print decrypted message printf("\n Decrypted message using AES-CBC mode : \r\n"); printf("\n %s \r\n",pText1); #endif /* Forever loop */ while(1); }
int main(int argc, char *argv[]) { if ( argc <= 1 ) usage(); parse_opts(argc,argv); if (str == NULL) usage(); lenstr = strlen(str); printf("%lu\n", lenstr); /*pad the message to multiple of 8 bytes*/ blok = lenstr / BLOCK_SIZE; baki = lenstr % BLOCK_SIZE; if (baki<=7) { blok ++; pad = (BLOCK_SIZE - baki); } else { printf("Padding Error\n"); return 1; } uint8_t newMessage[blok * BLOCK_SIZE * sizeof(uint8_t)]; memset(newMessage+lenstr,pad,pad); memcpy(newMessage,str, lenstr); lenmsg = sizeof(newMessage); /*padding ends*/ printf("Plaintext: %s\n",str ); printf("Padded Plaintext: \n" ); printMessage(newMessage,lenmsg); cbc_encrypt((uint8_t*)theKey,iv,newMessage,lenmsg); printf("\nEncrypted Ciphertext: \n"); printMessage(newMessage,lenmsg); cbc_decrypt((uint8_t*)theKey,iv,newMessage,lenmsg); printf("\nDecrypted Plaintext: \n"); printMessage(newMessage,lenmsg); //copy to new array with size + 1 pad = (int)newMessage[lenmsg-1]; uint8_t finMessage[lenmsg-pad+1]; memcpy (finMessage,newMessage,lenmsg-pad); //new array without padding printf("\nRemoved Padding: \n"); printMessage(finMessage,sizeof(finMessage)-1); //add NULL pointer to turn it into string memset (finMessage+lenmsg-pad,'\0',1); printf("Final String: %s\n",(char *)finMessage); return 0; }
bool CCCrypto::cbc_encrypt(const std::string &sData, block_encrypt_func encrypt_func, int iBlockSize, void *ctx, std::string &sResult) { return cbc_encrypt(sData.c_str(), sData.c_str() + sData.size(), encrypt_func, iBlockSize, ctx, sResult); }
/* * Perform an encrypt/decrypt operation to/from files using AES+CBC+PKCS7 pad. * Set encrypt to 1 to encrypt, 0 to decrypt. * * Input: in/out files, key, iv, and mode * Output: CRYPT_OK if no error * Side Effects: bytes slurped from infile, pushed to outfile, fds updated. */ int do_crypt(FILE *infd, FILE *outfd, unsigned char *key, unsigned char *iv, int encrypt) { union paddable inbuf, outbuf; int cipher, ret; symmetric_CBC cbc; size_t nb; /* Register your cipher! */ cipher = register_cipher(&aes_desc); if(cipher == -1) return CRYPT_INVALID_CIPHER; /* Start a CBC session with cipher/key/val params */ ret = cbc_start(cipher, iv, key, KEY_LENGTH, 0, &cbc); if( ret != CRYPT_OK ) return -1; do { /* Get bytes from the source */ nb = fread(inbuf.unpad, 1, sizeof(inbuf.unpad), infd); if(!nb) return encrypt ? CRYPT_OK : CRYPT_ERROR; /* Barf if we got a read error */ if(ferror(infd)) return CRYPT_ERROR; if(encrypt) { /* We're encrypting, so pad first (if at EOF) and then crypt */ if(feof(infd)) nb = pkcs7_pad(&inbuf, nb, aes_desc.block_length, 1); ret = cbc_encrypt(inbuf.pad, outbuf.pad, nb, &cbc); if(ret != CRYPT_OK) return ret; } else { /* We're decrypting, so decrypt and then unpad if at EOF */ ret = cbc_decrypt(inbuf.unpad, outbuf.unpad, nb, &cbc); if( ret != CRYPT_OK ) return ret; if( feof(infd) ) nb = pkcs7_pad(&outbuf, nb, aes_desc.block_length, 0); if(nb == 0) /* The file didn't decrypt correctly */ return CRYPT_ERROR; } /* Push bytes to outfile */ if(fwrite(outbuf.unpad, 1, nb, outfd) != nb) return CRYPT_ERROR; } while(!feof(infd)); /* Close up */ cbc_done(&cbc); return CRYPT_OK; }
int modes_test(void) { unsigned char pt[64], ct[64], tmp[64], key[16], iv[16], iv2[16]; int x, cipher_idx; symmetric_CBC cbc; symmetric_CFB cfb; symmetric_OFB ofb; symmetric_CTR ctr; unsigned long l; /* make a random pt, key and iv */ yarrow_read(pt, 64, &test_yarrow); yarrow_read(key, 16, &test_yarrow); yarrow_read(iv, 16, &test_yarrow); /* get idx of AES handy */ cipher_idx = find_cipher("aes"); if (cipher_idx == -1) { printf("test requires AES"); return 1; } /* test CBC mode */ /* encode the block */ DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc)); l = sizeof(iv2); DO(cbc_getiv(iv2, &l, &cbc)); if (l != 16 || memcmp(iv2, iv, 16)) { printf("cbc_getiv failed"); return 1; } for (x = 0; x < 4; x++) { DO(cbc_encrypt(pt+x*16, ct+x*16, &cbc)); } /* decode the block */ DO(cbc_setiv(iv2, l, &cbc)); zeromem(tmp, sizeof(tmp)); for (x = 0; x < 4; x++) { DO(cbc_decrypt(ct+x*16, tmp+x*16, &cbc)); } if (memcmp(tmp, pt, 64) != 0) { printf("CBC failed"); return 1; } /* test CFB mode */ /* encode the block */ DO(cfb_start(cipher_idx, iv, key, 16, 0, &cfb)); l = sizeof(iv2); DO(cfb_getiv(iv2, &l, &cfb)); /* note we don't memcmp iv2/iv since cfb_start processes the IV for the first block */ if (l != 16) { printf("cfb_getiv failed"); return 1; } DO(cfb_encrypt(pt, ct, 64, &cfb)); /* decode the block */ DO(cfb_setiv(iv, l, &cfb)); zeromem(tmp, sizeof(tmp)); DO(cfb_decrypt(ct, tmp, 64, &cfb)); if (memcmp(tmp, pt, 64) != 0) { printf("CFB failed"); return 1; } /* test OFB mode */ /* encode the block */ DO(ofb_start(cipher_idx, iv, key, 16, 0, &ofb)); l = sizeof(iv2); DO(ofb_getiv(iv2, &l, &ofb)); if (l != 16 || memcmp(iv2, iv, 16)) { printf("ofb_getiv failed"); return 1; } DO(ofb_encrypt(pt, ct, 64, &ofb)); /* decode the block */ DO(ofb_setiv(iv2, l, &ofb)); zeromem(tmp, sizeof(tmp)); DO(ofb_decrypt(ct, tmp, 64, &ofb)); if (memcmp(tmp, pt, 64) != 0) { printf("OFB failed"); return 1; } /* test CTR mode */ /* encode the block */ DO(ctr_start(cipher_idx, iv, key, 16, 0, &ctr)); l = sizeof(iv2); DO(ctr_getiv(iv2, &l, &ctr)); if (l != 16 || memcmp(iv2, iv, 16)) { printf("ctr_getiv failed"); return 1; } DO(ctr_encrypt(pt, ct, 64, &ctr)); /* decode the block */ DO(ctr_setiv(iv2, l, &ctr)); zeromem(tmp, sizeof(tmp)); DO(ctr_decrypt(ct, tmp, 64, &ctr)); if (memcmp(tmp, pt, 64) != 0) { printf("CTR failed"); return 1; } return 0; }
TEE_Result tee_cipher_update(void *ctx, uint32_t algo, TEE_OperationMode mode, bool last_block, const uint8_t *data, size_t len, uint8_t *dst) { TEE_Result res; int ltc_res = CRYPT_OK; size_t block_size; uint8_t tmp_block[64], tmp2_block[64]; int nb_blocks, len_last_block; struct symmetric_CTS *cts; /* * Check that the block contains the correct number of data, apart * for the last block in some XTS / CTR / XTS mode */ res = tee_cipher_get_block_size(algo, &block_size); if (res != TEE_SUCCESS) return res; if ((len % block_size) != 0) { if (!last_block) return TEE_ERROR_BAD_PARAMETERS; switch (algo) { case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_DES_ECB_NOPAD: case TEE_ALG_DES3_ECB_NOPAD: case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_DES_CBC_NOPAD: case TEE_ALG_DES3_CBC_NOPAD: return TEE_ERROR_BAD_PARAMETERS; case TEE_ALG_AES_CTR: case TEE_ALG_AES_XTS: case TEE_ALG_AES_CTS: /* * These modes doesn't require padding for the last * block. * * This isn't entirely true, both XTS and CTS can only * encrypt minimum one block and also they need at least * one complete block in the last update to finish the * encryption. The algorithms are supposed to detect * that, we're only making sure that all data fed up to * that point consists of complete blocks. */ break; default: return TEE_ERROR_NOT_SUPPORTED; } } switch (algo) { case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_DES_ECB_NOPAD: case TEE_ALG_DES3_ECB_NOPAD: if (mode == TEE_MODE_ENCRYPT) ltc_res = ecb_encrypt(data, dst, len, (symmetric_ECB *)ctx); else ltc_res = ecb_decrypt(data, dst, len, (symmetric_ECB *)ctx); break; case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_DES_CBC_NOPAD: case TEE_ALG_DES3_CBC_NOPAD: if (mode == TEE_MODE_ENCRYPT) ltc_res = cbc_encrypt(data, dst, len, (symmetric_CBC *)ctx); else ltc_res = cbc_decrypt(data, dst, len, (symmetric_CBC *)ctx); break; case TEE_ALG_AES_CTR: if (mode == TEE_MODE_ENCRYPT) ltc_res = ctr_encrypt(data, dst, len, (symmetric_CTR *)ctx); else ltc_res = ctr_decrypt(data, dst, len, (symmetric_CTR *)ctx); break; case TEE_ALG_AES_XTS: return TEE_ERROR_NOT_SUPPORTED; /* if (mode == TEE_MODE_ENCRYPT) { ltc_res = xts_encrypt(data, dst, len, (symmetric_xts *)ctx); } else { ltc_res = xts_decrypt(data, dst, len, (symmetric_xts *)ctx); } */ break; case TEE_ALG_AES_CTS: /* * From http://en.wikipedia.org/wiki/Ciphertext_stealing * CBC ciphertext stealing encryption using a standard * CBC interface: * 1. Pad the last partial plaintext block with 0. * 2. Encrypt the whole padded plaintext using the * standard CBC mode. * 3. Swap the last two ciphertext blocks. * 4. Truncate the ciphertext to the length of the * original plaintext. * * CBC ciphertext stealing decryption using a standard * CBC interface * 1. Dn = Decrypt (K, Cn-1). Decrypt the second to last * ciphertext block. * 2. Cn = Cn || Tail (Dn, B-M). Pad the ciphertext to the * nearest multiple of the block size using the last * B-M bits of block cipher decryption of the * second-to-last ciphertext block. * 3. Swap the last two ciphertext blocks. * 4. Decrypt the (modified) ciphertext using the standard * CBC mode. * 5. Truncate the plaintext to the length of the original * ciphertext. */ cts = (struct symmetric_CTS *)ctx; if (!last_block) return tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, last_block, data, len, dst); /* Compute the last block length and check constraints */ if (block_size > 64) return TEE_ERROR_BAD_STATE; nb_blocks = ((len + block_size - 1) / block_size); if (nb_blocks < 2) return TEE_ERROR_BAD_STATE; len_last_block = len % block_size; if (len_last_block == 0) len_last_block = block_size; if (mode == TEE_MODE_ENCRYPT) { memcpy(tmp_block, data + ((nb_blocks - 1) * block_size), len_last_block); memset(tmp_block + len_last_block, 0, block_size - len_last_block); res = tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, data, (nb_blocks - 1) * block_size, dst); if (res != TEE_SUCCESS) return res; memcpy(dst + (nb_blocks - 1) * block_size, dst + (nb_blocks - 2) * block_size, len_last_block); res = tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, tmp_block, block_size, dst + (nb_blocks - 2) * block_size); if (res != TEE_SUCCESS) return res; } else { /* 1. Decrypt the second to last ciphertext block */ res = tee_cipher_update( &cts->ecb, TEE_ALG_AES_ECB_NOPAD, mode, 0, data + (nb_blocks - 2) * block_size, block_size, tmp2_block); if (res != TEE_SUCCESS) return res; /* 2. Cn = Cn || Tail (Dn, B-M) */ memcpy(tmp_block, data + ((nb_blocks - 1) * block_size), len_last_block); memcpy(tmp_block + len_last_block, tmp2_block + len_last_block, block_size - len_last_block); /* 3. Swap the last two ciphertext blocks */ /* done by passing the correct buffers in step 4. */ /* 4. Decrypt the (modified) ciphertext */ if (nb_blocks > 2) { res = tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, data, (nb_blocks - 2) * block_size, dst); if (res != TEE_SUCCESS) return res; } res = tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, tmp_block, block_size, dst + ((nb_blocks - 2) * block_size)); if (res != TEE_SUCCESS) return res; res = tee_cipher_update( &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, data + ((nb_blocks - 2) * block_size), block_size, tmp_block); if (res != TEE_SUCCESS) return res; /* 5. Truncate the plaintext */ memcpy(dst + (nb_blocks - 1) * block_size, tmp_block, len_last_block); break; } break; default: return TEE_ERROR_NOT_SUPPORTED; } if (ltc_res == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; }
int modes_test(void) { unsigned char pt[64], ct[64], tmp[64], key[16], iv[16], iv2[16]; int cipher_idx; #ifdef LTC_CBC_MODE symmetric_CBC cbc; #endif #ifdef LTC_CFB_MODE symmetric_CFB cfb; #endif #ifdef LTC_OFB_MODE symmetric_OFB ofb; #endif unsigned long l; /* make a random pt, key and iv */ yarrow_read(pt, 64, &yarrow_prng); yarrow_read(key, 16, &yarrow_prng); yarrow_read(iv, 16, &yarrow_prng); /* get idx of AES handy */ cipher_idx = find_cipher("aes"); if (cipher_idx == -1) { fprintf(stderr, "test requires AES"); return 1; } #ifdef LTC_F8_MODE DO(f8_test_mode()); #endif #ifdef LTC_LRW_MODE DO(lrw_test()); #endif #ifdef LTC_CBC_MODE /* test CBC mode */ /* encode the block */ DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc)); l = sizeof(iv2); DO(cbc_getiv(iv2, &l, &cbc)); if (l != 16 || memcmp(iv2, iv, 16)) { fprintf(stderr, "cbc_getiv failed"); return 1; } DO(cbc_encrypt(pt, ct, 64, &cbc)); /* decode the block */ DO(cbc_setiv(iv2, l, &cbc)); zeromem(tmp, sizeof(tmp)); DO(cbc_decrypt(ct, tmp, 64, &cbc)); if (memcmp(tmp, pt, 64) != 0) { fprintf(stderr, "CBC failed"); return 1; } #endif #ifdef LTC_CFB_MODE /* test CFB mode */ /* encode the block */ DO(cfb_start(cipher_idx, iv, key, 16, 0, &cfb)); l = sizeof(iv2); DO(cfb_getiv(iv2, &l, &cfb)); /* note we don't memcmp iv2/iv since cfb_start processes the IV for the first block */ if (l != 16) { fprintf(stderr, "cfb_getiv failed"); return 1; } DO(cfb_encrypt(pt, ct, 64, &cfb)); /* decode the block */ DO(cfb_setiv(iv, l, &cfb)); zeromem(tmp, sizeof(tmp)); DO(cfb_decrypt(ct, tmp, 64, &cfb)); if (memcmp(tmp, pt, 64) != 0) { fprintf(stderr, "CFB failed"); return 1; } #endif #ifdef LTC_OFB_MODE /* test OFB mode */ /* encode the block */ DO(ofb_start(cipher_idx, iv, key, 16, 0, &ofb)); l = sizeof(iv2); DO(ofb_getiv(iv2, &l, &ofb)); if (l != 16 || memcmp(iv2, iv, 16)) { fprintf(stderr, "ofb_getiv failed"); return 1; } DO(ofb_encrypt(pt, ct, 64, &ofb)); /* decode the block */ DO(ofb_setiv(iv2, l, &ofb)); zeromem(tmp, sizeof(tmp)); DO(ofb_decrypt(ct, tmp, 64, &ofb)); if (memcmp(tmp, pt, 64) != 0) { fprintf(stderr, "OFB failed"); return 1; } #endif #ifdef LTC_CTR_MODE DO(ctr_test()); #endif return 0; }
int cbc_encrypt_tweaked(const unsigned char *pt, unsigned long len, unsigned char *ct, const unsigned char *tweak, symmetric_CBC *cbc) { (void) cbc_setiv(tweak, cbc->blocklen, cbc); return cbc_encrypt(pt, ct, len, cbc); }
static int RunCipherKAT( katvector *kat) { int err = CRYPT_OK; char* name = NULL; uint8_t *out = NULL; size_t alloc_len = MAX(kat->EBClen, kat->CBClen); symmetric_ECB ECB; symmetric_CBC CBC; out = malloc(alloc_len); ZERO(out, alloc_len); // err = cipher_is_valid(kat->algor); CKERR; name = cipher_name(kat->algor); printf("\t%-7s %d ", name, kat->keysize); printf("%6s", "ECB"); DO( ecb_start(kat->algor, kat->key, kat->keysize>>3, 0, &ECB)); DO( ecb_encrypt(kat->PT, out, kat->PTlen, &ECB)) /* check against know-answer */ DO( compareResults( kat->EBC, out, kat->EBClen , kResultFormat_Byte, "Symmetric Encrypt")); DO(ecb_decrypt(out, out, kat->PTlen, &ECB)); /* check against orginal plain-text */ DO(compareResults( kat->PT, out, kat->PTlen , kResultFormat_Byte, "Symmetric Decrypt")); printf("%6s", "CBC"); DO(cbc_start(kat->algor, kat->IV, kat->key, kat->keysize>>3, 0, &CBC)); DO(cbc_encrypt(kat->PT, out, kat->PTlen, &CBC)); /* check against know-answer */ DO(compareResults( kat->CBC, out, kat->CBClen , kResultFormat_Byte, "Symmetric Encrypt")); // reset CBC befire decrypt*/ cbc_done(&CBC); DO(cbc_start(kat->algor, kat->IV, kat->key, kat->keysize>>3, 0, &CBC)); DO(cbc_decrypt(out, out, kat->PTlen, &CBC)); /* check against orginal plain-text */ DO( compareResults( kat->PT, out, kat->PTlen , kResultFormat_Byte, "Symmetric Decrypt")); done: ecb_done(&ECB); cbc_done(&CBC); free(out); printf("\n"); return err; }
// ========================================================================= // Encrypt/Decrypt function // Note: PlaintextLength must be set to the size of the PlaintextData buffer on // entry; on exit, this will be set to the size of the buffer used. NTSTATUS ImpCypherCryptData( IN GUID* CypherGUID, IN LARGE_INTEGER SectorID, IN int SectorSize, // In bytes IN int KeyLength, // In bits IN FREEOTFEBYTE* Key, IN char* KeyASCII, // ASCII representation of "Key" IN int IVLength, // In bits IN FREEOTFEBYTE* IV, IN BOOLEAN encryptNotDecrypt, // TRUE = encrypt; FALSE = decrypt IN int InLength, // In bytes IN FREEOTFEBYTE* InData, OUT FREEOTFEBYTE* OutData ) { NTSTATUS status = STATUS_SUCCESS; // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL char ltcNullIV[FREEOTFE_MAX_CYPHER_BLOCKSIZE]; int cipher; symmetric_CBC *cbc; symmetric_LRW *lrw; symmetric_xts *xts; int errnum; CYPHER_MODE mode; int keySizeUnderlying; LARGE_INTEGER blockID64; INTEGER_128 blockID128; DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherDecryptData\n"))); status = DetermineCypherDetails( CypherGUID, &keySizeUnderlying, &mode ); // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL if ( (IVLength == 0) || (IV == NULL) ) { FREEOTFE_MEMZERO(<cNullIV, sizeof(ltcNullIV)); IV = (char*)<cNullIV; } // Sanity check on key supplied if NT_SUCCESS(status) { switch (mode) { case CYPHER_MODE_CBC: { if (KeyLength != keySizeUnderlying) { status = STATUS_INVALID_PARAMETER; } break; } case CYPHER_MODE_XTS: { if (KeyLength != (2 * keySizeUnderlying)) { status = STATUS_INVALID_PARAMETER; } break; } case CYPHER_MODE_LRW: { if (KeyLength != (keySizeUnderlying + (twofish_desc.block_length * 8))) { status = STATUS_INVALID_PARAMETER; } break; } } } if NT_SUCCESS(status) { status = InitLTCCypher(&cipher); } if NT_SUCCESS(status) { switch (mode) { case CYPHER_MODE_CBC: { cbc = FREEOTFE_MEMALLOC(sizeof(symmetric_CBC)); FREEOTFE_MEMZERO(cbc, sizeof(symmetric_CBC)); // Start a CBC session if ((errnum = cbc_start( cipher, IV, Key, (keySizeUnderlying/8), 0, cbc )) != CRYPT_OK) { status = STATUS_UNSUCCESSFUL; DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start CBC session (errnum: %d)\n"), errnum)); } else { if (encryptNotDecrypt) { if ((errnum = cbc_encrypt( InData, OutData, InLength, cbc )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } else { if ((errnum = cbc_decrypt( InData, OutData, InLength, cbc )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } cbc_done(cbc); } SecZeroMemory(cbc, sizeof(symmetric_CBC)); FREEOTFE_FREE(cbc); break; } case CYPHER_MODE_LRW: { lrw = FREEOTFE_MEMALLOC(sizeof(symmetric_LRW)); FREEOTFE_MEMZERO(lrw, sizeof(symmetric_LRW)); // Generate index in correct format // LRW uses: // *) The block index (i.e. the number of 128 bit blocks) // *) The first block has block index 1 - not 0! // *) Bigendian format // Note: LTC increments this itself as it processes each block SectorIDToBlockIdx_64Bit(SectorID, SectorSize, &blockID64); LARGE_INTEGER__To__INTEGER_128_BigEndian( blockID64, blockID128 ); IV = blockID128; // Start a LRW session if ((errnum = lrw_start( cipher, IV, Key, (keySizeUnderlying/8), // 128 bits tweak key begins after the // cypher key (Key + (keySizeUnderlying/8)), 0, lrw )) != CRYPT_OK) { status = STATUS_UNSUCCESSFUL; DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start LRW session (errnum: %d)\n"), errnum)); } else { if (encryptNotDecrypt) { if ((errnum = lrw_encrypt( InData, OutData, InLength, lrw )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } else { if ((errnum = lrw_decrypt( InData, OutData, InLength, lrw )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } lrw_done(lrw); } SecZeroMemory(lrw, sizeof(symmetric_LRW)); FREEOTFE_FREE(lrw); break; } case CYPHER_MODE_XTS: { xts = FREEOTFE_MEMALLOC(sizeof(symmetric_xts)); FREEOTFE_MEMZERO(xts, sizeof(symmetric_xts)); // Generate index in correct format // XTS uses: // *) The sector index (i.e. the number of N-bit sectors) // *) The first sector is sector 0 // *) Littleendian format LARGE_INTEGER__To__INTEGER_128_LittleEndian( SectorID, blockID128 ); // Start an XTS session if ((errnum = xts_start( cipher, Key, &(Key[keySizeUnderlying/8]), (keySizeUnderlying/8), 0, xts )) != CRYPT_OK) { status = STATUS_UNSUCCESSFUL; DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start XTS session (errnum: %d)\n"), errnum)); } else { if (encryptNotDecrypt) { if ((errnum = xts_encrypt( InData, InLength, OutData, blockID128, xts )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } else { if ((errnum = xts_decrypt( InData, InLength, OutData, blockID128, xts )) != CRYPT_OK) { DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum)); status = STATUS_UNSUCCESSFUL; } } xts_done(xts); } SecZeroMemory(xts, sizeof(symmetric_xts)); FREEOTFE_FREE(xts); break; } } } DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("ImpCypherDecryptData\n"))); return status; }
int cbctest(int type) { unsigned char test_string[TEST_SIZE]; char iv[CBC_MAX_IV_SIZE]; cbc_handle_t ch; void *eh; int ret; int i; switch (type) { case CBC_DES3_TYPE: ret = des3_init(&eh); break; case CBC_AES_128_TYPE: ret = aes_init(&eh); break; case CBC_AES_192_TYPE: ret = aes_init(&eh); break; case CBC_AES_256_TYPE: ret = aes_init(&eh); break; default: (void) printf("Illegal encryption type\n"); return (-1); } if (ret != 0) { (void) printf("Error initializing encryption algorithm\n"); return (-1); } bzero(iv, CBC_MAX_IV_SIZE); switch (type) { case CBC_DES3_TYPE: des3_key(eh, (uint8_t *)DES3_KEY); cbc_makehandle(&ch, eh, DES3_KEY_SIZE, DES3_BLOCK_SIZE, DES3_IV_SIZE, des3_encrypt, des3_decrypt); break; case CBC_AES_128_TYPE: aes_key(eh, (uint8_t *)AES_128_KEY, AES_128_KEY_SIZE); cbc_makehandle(&ch, eh, AES_128_KEY_SIZE, AES_BLOCK_SIZE, AES_IV_SIZE, aes_encrypt, aes_decrypt); break; case CBC_AES_192_TYPE: aes_key(eh, (uint8_t *)AES_192_KEY, AES_192_KEY_SIZE); cbc_makehandle(&ch, eh, AES_192_KEY_SIZE, AES_BLOCK_SIZE, AES_IV_SIZE, aes_encrypt, aes_decrypt); break; case CBC_AES_256_TYPE: aes_key(eh, (uint8_t *)AES_256_KEY, AES_256_KEY_SIZE); cbc_makehandle(&ch, eh, AES_256_KEY_SIZE, AES_BLOCK_SIZE, AES_IV_SIZE, aes_encrypt, aes_decrypt); break; default: /* Should not happen */ (void) printf("Illegal encryption type\n"); return (-1); } (void) strcpy((char *)test_string, TEST); for (i = 0; i < TEST_SIZE; i += TEST_BLOCK_SIZE) { (void) cbc_encrypt(&ch, (uint8_t *)&test_string[i], TEST_BLOCK_SIZE, (uint8_t *)iv); } if (strcmp((char *)test_string, TEST) == 0) { (void) printf("FAILED [Encryption]\n"); goto out; } bzero(iv, CBC_MAX_IV_SIZE); for (i = 0; i < TEST_SIZE; i += TEST_BLOCK_SIZE) { (void) cbc_decrypt(&ch, (uint8_t *)&test_string[i], TEST_BLOCK_SIZE, (uint8_t *)iv); } if (strcmp((char *)test_string, TEST) == 0) { (void) printf("PASSED\n"); } else { (void) printf("FAILED [Decryption]\n"); } out: switch (type) { case CBC_DES3_TYPE: des3_fini(eh); break; case CBC_AES_128_TYPE: case CBC_AES_192_TYPE: case CBC_AES_256_TYPE: aes_fini(eh); break; default: /* Should not happen */ (void) printf("Illegal encryption type\n"); return (-1); } return (0); }
/* encrypt the writepayload, putting into writebuf, ready for write_packet() * to put on the wire */ void encrypt_packet() { unsigned char padlen; unsigned char blocksize, macsize; buffer * writebuf; /* the packet which will go on the wire */ buffer * clearwritebuf; /* unencrypted, possibly compressed */ TRACE(("enter encrypt_packet()")); TRACE(("encrypt_packet type is %d", ses.writepayload->data[0])); blocksize = ses.keys->trans_algo_crypt->blocksize; macsize = ses.keys->trans_algo_mac->hashsize; /* Encrypted packet len is payload+5, then worst case is if we are 3 away * from a blocksize multiple. In which case we need to pad to the * multiple, then add another blocksize (or MIN_PACKET_LEN) */ clearwritebuf = buf_new((ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3 #ifndef DISABLE_ZLIB + ZLIB_COMPRESS_INCR /* bit of a kludge, but we can't know len*/ #endif ); buf_setlen(clearwritebuf, PACKET_PAYLOAD_OFF); buf_setpos(clearwritebuf, PACKET_PAYLOAD_OFF); buf_setpos(ses.writepayload, 0); #ifndef DISABLE_ZLIB /* compression */ if (ses.keys->trans_algo_comp == DROPBEAR_COMP_ZLIB) { buf_compress(clearwritebuf, ses.writepayload, ses.writepayload->len); } else #endif { memcpy(buf_getwriteptr(clearwritebuf, ses.writepayload->len), buf_getptr(ses.writepayload, ses.writepayload->len), ses.writepayload->len); buf_incrwritepos(clearwritebuf, ses.writepayload->len); } /* finished with payload */ buf_setpos(ses.writepayload, 0); buf_setlen(ses.writepayload, 0); /* length of padding - packet length must be a multiple of blocksize, * with a minimum of 4 bytes of padding */ padlen = blocksize - (clearwritebuf->len) % blocksize; if (padlen < 4) { padlen += blocksize; } /* check for min packet length */ if (clearwritebuf->len + padlen < MIN_PACKET_LEN) { padlen += blocksize; } buf_setpos(clearwritebuf, 0); /* packet length excluding the packetlength uint32 */ buf_putint(clearwritebuf, clearwritebuf->len + padlen - 4); /* padding len */ buf_putbyte(clearwritebuf, padlen); /* actual padding */ buf_setpos(clearwritebuf, clearwritebuf->len); buf_incrlen(clearwritebuf, padlen); genrandom(buf_getptr(clearwritebuf, padlen), padlen); /* do the actual encryption */ buf_setpos(clearwritebuf, 0); /* create a new writebuffer, this is freed when it has been put on the * wire by writepacket() */ writebuf = buf_new(clearwritebuf->len + macsize); if (ses.keys->trans_algo_crypt->cipherdesc == NULL) { /* copy it */ memcpy(buf_getwriteptr(writebuf, clearwritebuf->len), buf_getptr(clearwritebuf, clearwritebuf->len), clearwritebuf->len); buf_incrwritepos(writebuf, clearwritebuf->len); } else { /* encrypt it */ while (clearwritebuf->pos < clearwritebuf->len) { if (cbc_encrypt(buf_getptr(clearwritebuf, blocksize), buf_getwriteptr(writebuf, blocksize), &ses.keys->trans_symmetric_struct) != CRYPT_OK) { dropbear_exit("error encrypting"); } buf_incrpos(clearwritebuf, blocksize); buf_incrwritepos(writebuf, blocksize); } } /* now add a hmac and we're done */ writemac(writebuf, clearwritebuf); /* clearwritebuf is finished with */ buf_free(clearwritebuf); /* enqueue the packet for sending */ buf_setpos(writebuf, 0); enqueue(&ses.writequeue, (void*)writebuf); /* Update counts */ ses.kexstate.datatrans += writebuf->len; ses.transseq++; TRACE(("leave encrypt_packet()")); }
static int cbc_encryptfinal(drew_mode_t *ctx, uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { cbc_encrypt(ctx, out, in, inlen); return inlen; }