/** ********************************************************************* * @file rc5.cpp * @author petrucio@inf.ufsc.br ********************************************************************/ /*** * Includes ***********************************/ #include "rc5.h" #include #include #include /** ********************************************************************* * RC5 Constructor ********************************************************************/ RC5::RC5(void) { this->xkey = NULL; this->rounds = 12; } /** ********************************************************************* * RC5 Key Constructor from generic data ********************************************************************/ RC5::Key::Key(const UCHAR *data, int size) { this->bytes = (UCHAR*) malloc (size); memcpy(this->bytes, data, size); this->nbytes = size; this->nwords = (UCHAR) ceil(8 * this->nbytes / WSIZE); // ceil(8*key_bytes/word_bits) } /** ********************************************************************* * Constructs an RC5::Block, and updates the data ptr ********************************************************************/ RC5::Block::Block(UCHAR **data) { memcpy(&this->word0, *data, (WSIZE / 8)); *data += (int) (WSIZE / 8); memcpy(&this->word1, *data, (WSIZE / 8)); } /** ********************************************************************* * Constructs an RC5::Block from generic data ********************************************************************/ RC5::Block::Block(const UCHAR *data) { memcpy(&this->word0, data, WSIZE / 8); memcpy(&this->word1, (data + (WSIZE / 8)), WSIZE / 8); } /** ********************************************************************* * Extracts the data from block into output; ********************************************************************/ void RC5::Block::extract(UCHAR *output) { memcpy (output, &this->word0, WSIZE / 8); memcpy (output + (WSIZE/8), &this->word1, WSIZE / 8); } /** ********************************************************************* * RC5 Expanded key constructor from normal key ********************************************************************/ RC5::XKey::XKey(const RC5::Key &key) { int i, j, k; WORD A, B; WORD L[key.nwords]; UCHAR b = key.nbytes; UCHAR t = this->nwords = 2 * (b + 1); this->words = (WORD*) malloc (t * WSIZE); // Initialize L for (i=b-1, L[key.nwords-1]=0; i!=-1; i--) { L[i/BPW] = (L[i/BPW] << 8) + key.bytes[i]; } // Initialize xkey for (this->words[0]=magicP, i=1; iwords[i] = this->words[i-1] + magicQ; } // Mix key&L into xkey for (A=B=i=j=k=0; k<3*t; k++, i=(i+1)%t, j=(j+1)%key.nwords) { A = this->words[i] = ROTL(this->words[i] + (A + B), 3); B = L[j] = ROTL(L[j] + (A + B), (A + B)); } } /** ********************************************************************* * Sets the global expanded key to be used in future calls to * crypt and decrypt from a normal key. * * @param key: normal key, to be expanded and used as the global key ********************************************************************/ void RC5::setKey(const RC5::Key &key) { if (this->xkey) delete this->xkey; this->xkey = new RC5::XKey(key); } /** ********************************************************************* * Sets the number of rounds to be used for encryption and decryption * * @param rounds: numbers of rounds (one of the 3 rc5 parameters) ********************************************************************/ void RC5::setRounds(UCHAR rounds) { this->rounds = rounds; } /** ********************************************************************* * Criptografa um bloco (2 palavras) ********************************************************************/ RC5::Block RC5::encrypt(const RC5::Block &block) { assert(this->xkey != NULL); RC5::Block out_block; WORD A = block.word0 + this->xkey->words[0]; WORD B = block.word1 + this->xkey->words[1]; for (int i = 1; i <= this->rounds; i++) { A = ROTL(A ^ B, B) + this->xkey->words[2 * i]; B = ROTL(B ^ A, A) + this->xkey->words[2 * i + 1]; } out_block.word0 = A; out_block.word1 = B; return out_block; } /** ********************************************************************* * Descriptografa um bloco (2 palavras) ********************************************************************/ RC5::Block RC5::decrypt(const RC5::Block &block) { assert(this->xkey != NULL); RC5::Block out_block; WORD B = block.word1; WORD A = block.word0; for (int i = this->rounds; i > 0; i--) { B = ROTR(B - this->xkey->words[2 * i + 1], A) ^ A; A = ROTR(A - this->xkey->words[2 * i], B) ^ B; } out_block.word1 = B - this->xkey->words[1]; out_block.word0 = A - this->xkey->words[0]; return out_block; }