/** XTS Encryption @param pt [in] Plaintext @param ptlen Length of plaintext (and ciphertext) @param ct [out] Ciphertext @param tweak [in] The 128--bit encryption tweak (e.g. sector number) @param xts The XTS structure Returns CRYPT_OK upon success */ int xts_encrypt( const uint8_t *pt, unsigned long ptlen, uint8_t *ct, const uint8_t *tweak, symmetric_xts *xts) { aesedp_encrypt_ctx *encrypt_ctx = &xts->key1.encrypt; uint8_t PP[16], CC[16], T[16]; uint32_t i, m, mo, lim; uint32_t err; /* check inputs */ if((pt == 0) || (ct == 0)|| (tweak == 0) || (xts == 0)) return 1; /* get number of blocks */ m = ptlen >> 4; mo = ptlen & 15; /* must have at least one full block */ if (m == 0) { return CRYPT_INVALID_ARG; } /* encrypt the tweak */ if ((err = aes_encrypt(tweak, T, &xts->key2.encrypt)) != 0) { return CRYPT_INVALID_KEYSIZE; } /* for i = 0 to m-2 do */ if (mo == 0) { lim = m; } else { lim = m - 1; } for (i = 0; i < lim; i++) { err = tweak_crypt(pt, ct, T, encrypt_ctx); ct += 16; pt += 16; } /* if ptlen not divide 16 then */ if (mo > 0) { /* CC = tweak encrypt block m-1 */ if ((err = tweak_crypt(pt, CC, T, encrypt_ctx)) != 0) { return err; } /* Cm = first ptlen % 16 bytes of CC */ for (i = 0; i < mo; i++) { PP[i] = pt[16+i]; ct[16+i] = CC[i]; } for (; i < 16; i++) { PP[i] = CC[i]; } /* Cm-1 = Tweak encrypt PP */ if ((err = tweak_crypt(PP, ct, T, encrypt_ctx)) != 0) { return err; } } return err; }
/** XTS Encryption @param pt [in] Plaintext @param ptlen Length of plaintext (and ciphertext) @param ct [out] Ciphertext @param tweak [in] The 128--bit encryption tweak (e.g. sector number) @param xts The XTS structure Returns CRYPT_OK upon success */ int xts_encrypt(const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tweak, symmetric_xts *xts) { unsigned char PP[16], CC[16], T[16]; unsigned long i, m, mo, lim; int err; /* check inputs */ LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tweak != NULL); LTC_ARGCHK(xts != NULL); /* check if valid */ if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) { return err; } /* get number of blocks */ m = ptlen >> 4; mo = ptlen & 15; /* must have at least one full block */ if (m == 0) { return CRYPT_INVALID_ARG; } if (mo == 0) { lim = m; } else { lim = m - 1; } if (cipher_descriptor[xts->cipher].accel_xts_encrypt && lim > 0) { /* use accelerated encryption for whole blocks */ if ((err = cipher_descriptor[xts->cipher].accel_xts_encrypt(pt, ct, lim, tweak, &xts->key1, &xts->key2) != CRYPT_OK)) { return err; } ct += lim * 16; pt += lim * 16; /* tweak is encrypted on output */ XMEMCPY(T, tweak, sizeof(T)); } else { /* encrypt the tweak */ if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) { return err; } for (i = 0; i < lim; i++) { err = tweak_crypt(pt, ct, T, xts); ct += 16; pt += 16; } } /* if ptlen not divide 16 then */ if (mo > 0) { /* CC = tweak encrypt block m-1 */ if ((err = tweak_crypt(pt, CC, T, xts)) != CRYPT_OK) { return err; } /* Cm = first ptlen % 16 bytes of CC */ for (i = 0; i < mo; i++) { PP[i] = pt[16 + i]; ct[16 + i] = CC[i]; } for (; i < 16; i++) { PP[i] = CC[i]; } /* Cm-1 = Tweak encrypt PP */ if ((err = tweak_crypt(PP, ct, T, xts)) != CRYPT_OK) { return err; } } /* Decrypt the tweak back */ if ((err = cipher_descriptor[xts->cipher].ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) { return err; } return err; }
/** XTS Encryption @param pt [in] Plaintext @param ptlen Length of plaintext (and ciphertext) @param ct [out] Ciphertext @param tweak [in] The 128--bit encryption tweak (e.g. sector number) @param xts The XTS structure Returns CRYPT_OK upon success */ int xts_encrypt( void *context, ltc_gladman_set_key MethodSetKey, ltc_gladman_encrypt MethodEncrypt, int Key1Length, // In bits FREEOTFEBYTE* Key1, int Key2Length, // In bits FREEOTFEBYTE* Key2, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, const unsigned char *tweak //ltc-orig symmetric_xts *xts ) { unsigned char PP[16], CC[16], T[16]; unsigned long i, m, mo, lim; int err; /* check inputs */ LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tweak != NULL); //ltc-orig LTC_ARGCHK(xts != NULL); //ltc-orig /* check if valid */ //ltc-orig if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) { //ltc-orig return err; //ltc-orig } /* get number of blocks */ m = ptlen >> 4; mo = ptlen & 15; /* must have at least one full block */ if (m == 0) { return CRYPT_INVALID_ARG; } /* encrypt the tweak */ //ltc-orig if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) { //ltc-orig return err; //ltc-orig } MethodSetKey(context, Key2, Key2Length, enc); MethodEncrypt(context, tweak, T); /* for i = 0 to m-2 do */ if (mo == 0) { lim = m; } else { lim = m - 1; } MethodSetKey(context, Key1, Key1Length, enc); for (i = 0; i < lim; i++) { //ltc-orig err = tweak_crypt(pt, ct, T, xts); err = tweak_crypt(context, MethodEncrypt, pt, ct, T); ct += 16; pt += 16; } /* if ptlen not divide 16 then */ if (mo > 0) { /* CC = tweak encrypt block m-1 */ //ltc-orig if ((err = tweak_crypt(pt, CC, T, xts)) != CRYPT_OK) { if ((err = tweak_crypt(context, MethodEncrypt, pt, CC, T)) != CRYPT_OK) { return err; } /* Cm = first ptlen % 16 bytes of CC */ for (i = 0; i < mo; i++) { PP[i] = pt[16+i]; ct[16+i] = CC[i]; } for (; i < 16; i++) { PP[i] = CC[i]; } /* Cm-1 = Tweak encrypt PP */ //ltc-orig if ((err = tweak_crypt(PP, ct, T, xts)) != CRYPT_OK) { if ((err = tweak_crypt(context, MethodEncrypt, PP, ct, T)) != CRYPT_OK) { return err; } } return err; }