ChaCha20 and put everything in folder

This commit is contained in:
y4my4my4m 2023-12-29 17:26:08 -05:00
parent 2b847de048
commit 50a931073b
4 changed files with 247 additions and 58 deletions

View file

@ -1,5 +1,5 @@
#define Nb 4 #define Nb 4 // The number of columns comprising a state in AES. This is a constant in AES. Value=4
#define Nk 4 #define Nk 4 // The number of 32 bit words in a key.
#define Nr 10 // amount of rounds to expand the key #define Nr 10 // amount of rounds to expand the key
// could be calculated on the fly too... i guess // could be calculated on the fly too... i guess
@ -79,40 +79,49 @@ U0 InitMulTables() {
} }
U0 KeyExpansion(U8 *RoundKey, U8 *Key) { U0 KeyExpansion(U8 *RoundKey, U8 *Key) {
I64 i, j; I64 i, j, k;
// Copy the original key to the round key U8 tempa[4]; // Temporary storage array
for (i = 0; i < Nk; i++) {
// Copy the original key to the first round key
for (i = 0; i < Nk; ++i) {
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
} }
// Expand the round key // Expand the keys for the remaining rounds
for (i = Nk; i < Nb * (Nr + 1); i++) { for (i = Nk; i < Nb * (Nr + 1); ++i) {
U8 temp[4]; // Fetch the previous word
for (j = 0; j < 4; j++) { k = (i - 1) * 4;
temp[j] = RoundKey[(i-1) * 4 + j]; tempa[0] = RoundKey[k + 0];
} tempa[1] = RoundKey[k + 1];
tempa[2] = RoundKey[k + 2];
tempa[3] = RoundKey[k + 3];
if (i % Nk == 0) { if (i % Nk == 0) {
// Perform the rotation within temp array, substitute with S-box, then XOR with Rcon[i/Nk] // Rotate the word and apply S-box substitution
I64 k = temp[0]; // should be I64 but kept throwing a warning about 64bit variable somehow??? U8 u8tmp = tempa[0];
k = k & 0xff; // this is an attempt at forcing U8 tempa[0] = sBox[tempa[1]];
temp[0] = sBox[temp[1]] ^ Rcon[i/Nk]; tempa[1] = sBox[tempa[2]];
temp[1] = sBox[temp[2]]; tempa[2] = sBox[tempa[3]];
temp[2] = sBox[temp[3]]; tempa[3] = sBox[u8tmp];
temp[3] = sBox[k];
// XOR with Rcon[i/Nk]
tempa[0] = tempa[0] ^ Rcon[i / Nk];
} }
for (j = 0; j < 4; j++) { // XOR tempa with the word Nk positions before
RoundKey[i * 4 + j] = RoundKey[(i - Nk) * 4 + j] ^ temp[j]; j = i * 4; k = (i - Nk) * 4;
} RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];
RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];
RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];
RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];
} }
} }
U0 AddRoundKey(U8 round, U8 *state, U8 *RoundKey) { U0 AddRoundKey(U8 round, U8 *state, U8 *RoundKey) {
I64 i,j; I64 i, j;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++) {
state[j * 4 + i] ^= RoundKey[round * Nb * 4 + i * Nb + j]; state[j * 4 + i] ^= RoundKey[round * Nb * 4 + i * Nb + j];
@ -128,47 +137,47 @@ U0 SubBytes(U8 *state) {
} }
U0 ShiftRows(U8 *state) { U0 ShiftRows(U8 *state) {
I64 i; U8 temp;
U8 temp[16];
// Store state in temp // Shift the second row (1 shift to the left)
for (i = 0; i < 16; i++) { temp = state[1];
temp[i] = state[i]; state[1] = state[5];
} state[5] = state[9];
state[9] = state[13];
state[13] = temp;
// Shift first row 1 columns to left // Shift the third row (2 shifts to the left)
state[0] = temp[0]; temp = state[2];
state[4] = temp[5]; state[2] = state[10];
state[8] = temp[10]; state[10] = temp;
state[12] = temp[15]; temp = state[6];
state[6] = state[14];
state[14] = temp;
// Shift third row 2 steps to the left // Shift the fourth row (3 shifts to the left)
state[2] = temp[10]; temp = state[3];
state[6] = temp[14]; state[3] = state[15];
state[10] = temp[2]; state[15] = state[11];
state[14] = temp[6]; state[11] = state[7];
state[7] = temp;
// Shift fourth row 3 steps to the left
state[3] = temp[15];
state[7] = temp[3];
state[11] = temp[7];
state[15] = temp[11];
} }
U0 MixColumns(U8 *state) { U0 MixColumns(U8 *state) {
U8 temp[16]; for (I64 i = 0; i < 4; ++i) {
I64 i; U8 a0 = state[i * 4 + 0];
U8 a1 = state[i * 4 + 1];
U8 a2 = state[i * 4 + 2];
U8 a3 = state[i * 4 + 3];
// Store state in temp U8 r0 = Mul2[a0] ^ Mul3[a1] ^ a2 ^ a3;
for (i = 0; i < 16; i++) { U8 r1 = a0 ^ Mul2[a1] ^ Mul3[a2] ^ a3;
temp[i] = state[i]; U8 r2 = a0 ^ a1 ^ Mul2[a2] ^ Mul3[a3];
} U8 r3 = Mul3[a0] ^ a1 ^ a2 ^ Mul2[a3];
for (i = 0; i < 4; i++) { state[i * 4 + 0] = r0;
state[i * 4 + 0] = Mul2[temp[i * 4 + 0]] ^ Mul3[temp[i * 4 + 1]] ^ temp[i * 4 + 2] ^ temp[i * 4 + 3]; state[i * 4 + 1] = r1;
state[i * 4 + 1] = temp[i * 4 + 0] ^ Mul2[temp[i * 4 + 1]] ^ Mul3[temp[i * 4 + 2]] ^ temp[i * 4 + 3]; state[i * 4 + 2] = r2;
state[i * 4 + 2] = temp[i * 4 + 0] ^ temp[i * 4 + 1] ^ Mul2[temp[i * 4 + 2]] ^ Mul3[temp[i * 4 + 3]]; state[i * 4 + 3] = r3;
state[i * 4 + 3] = Mul3[temp[i * 4 + 0]] ^ temp[i * 4 + 1] ^ temp[i * 4 + 2] ^ Mul2[temp[i * 4 + 3]];
} }
} }
@ -249,9 +258,9 @@ U8 HexCharToByte(U8 ch) {
} }
U0 HexStringToByteArray(U8 *hexString, U8 *byteArray, I64 byteArrayLength) { U0 HexStringToByteArray(U8 *hexString, U8 *byteArray, I64 byteArrayLength) {
I64 i; I64 i;
for (i = 0; i < byteArrayLength; i++) { for (i = 0; i < byteArrayLength; i++) {
byteArray[i] = HexCharToByte(hexString[2*i]) << 4 | HexCharToByte(hexString[2*i + 1]); byteArray[i] = HexCharToByte(hexString[2 * i]) << 4 | HexCharToByte(hexString[2 * i + 1]);
} }
} }
@ -264,7 +273,6 @@ U0 Main() {
U8 ctx[176]; // Context (expanded key) U8 ctx[176]; // Context (expanded key)
InitMulTables(); InitMulTables();
AES_init_ctx(ctx, key); AES_init_ctx(ctx, key);
AES_ECB_encrypt(ctx, buf); AES_ECB_encrypt(ctx, buf);

View file

@ -0,0 +1,181 @@
// Rotating bits left
U32 RotL32(U32 x, I32 n) {
return (x << n) | (x >> (32 - n));
}
// Packing bytes into a 32-bit unsigned integer
U32 Pack4(U8 *a) {
U32 res = 0;
res |= a[0](U32) << 0 * 8;
res |= a[1](U32) << 1 * 8;
res |= a[2](U32) << 2 * 8;
res |= a[3](U32) << 3 * 8;
return res;
}
// Unpacking a 32-bit unsigned integer into bytes
U0 UnPack4(U32 src, U8 *dst) {
dst[0] = (src >> 0 * 8) & 0xff;
dst[1] = (src >> 1 * 8) & 0xff;
dst[2] = (src >> 2 * 8) & 0xff;
dst[3] = (src >> 3 * 8) & 0xff;
}
// ChaCha20 context structure
class chacha20_context {
U32 state[16];
U32 keystream32[16];
U8 key[32];
U8 nonce[12];
U64 counter;
U32 position;
};
U8 *magic_constant = "expand 32-byte k";
// Initializing the ChaCha20 block
U0 chacha20_init_block(chacha20_context *ctx, U8 *key, U8 *nonce) {
MemCopy(ctx->key, key, 32);
MemCopy(ctx->nonce, nonce, 12);
ctx->state[0] = Pack4(magic_constant + 0 * 4);
ctx->state[1] = Pack4(magic_constant + 1 * 4);
ctx->state[2] = Pack4(magic_constant + 2 * 4);
ctx->state[3] = Pack4(magic_constant + 3 * 4);
ctx->state[4] = Pack4(key + 0 * 4);
ctx->state[5] = Pack4(key + 1 * 4);
ctx->state[6] = Pack4(key + 2 * 4);
ctx->state[7] = Pack4(key + 3 * 4);
ctx->state[8] = Pack4(key + 4 * 4);
ctx->state[9] = Pack4(key + 5 * 4);
ctx->state[10] = Pack4(key + 6 * 4);
ctx->state[11] = Pack4(key + 7 * 4);
// 64 bit counter initialized to zero by default.
ctx->state[12] = 0;
ctx->state[13] = Pack4(nonce + 0 * 4);
ctx->state[14] = Pack4(nonce + 1 * 4);
ctx->state[15] = Pack4(nonce + 2 * 4);
MemCopy(ctx->nonce, nonce, 12);
}
// Setting the counter for the ChaCha20 block
U0 chacha20_block_set_counter(chacha20_context *ctx, U64 counter) {
ctx->state[12] = counter(U32);
ctx->state[13] = Pack4(ctx->nonce + 0 * 4) + (counter >> 32)(U32);
}
U0 CHACHA20_QUARTERROUND(U32 *x, I32 a, I32 b, I32 c, I32 d) {
x[a] += x[b]; x[d] = RotL32(x[d] ^ x[a], 16);
x[c] += x[d]; x[b] = RotL32(x[b] ^ x[c], 12);
x[a] += x[b]; x[d] = RotL32(x[d] ^ x[a], 8);
x[c] += x[d]; x[b] = RotL32(x[b] ^ x[c], 7);
}
// Generating the next ChaCha20 block
U0 chacha20_block_next(chacha20_context *ctx) {
I32 i;
for (i = 0; i < 16; i++) ctx->keystream32[i] = ctx->state[i];
for (i = 0; i < 10; i++) {
CHACHA20_QUARTERROUND(ctx->keystream32, 0, 4, 8, 12);
CHACHA20_QUARTERROUND(ctx->keystream32, 1, 5, 9, 13);
CHACHA20_QUARTERROUND(ctx->keystream32, 2, 6, 10, 14);
CHACHA20_QUARTERROUND(ctx->keystream32, 3, 7, 11, 15);
CHACHA20_QUARTERROUND(ctx->keystream32, 0, 5, 10, 15);
CHACHA20_QUARTERROUND(ctx->keystream32, 1, 6, 11, 12);
CHACHA20_QUARTERROUND(ctx->keystream32, 2, 7, 8, 13);
CHACHA20_QUARTERROUND(ctx->keystream32, 3, 4, 9, 14);
}
for (i = 0; i < 16; i++) ctx->keystream32[i] += ctx->state[i];
U32 *counter = ctx->state + 12;
counter[0]++;
if (counter[0] == 0) {
counter[1]++;
if (counter[1] == 0) {
// Handle the counter overflow, e.g., print an error message
Print("Counter overflow detected\n");
// Exit();
}
}
}
// Initializing the ChaCha20 context
U0 chacha20_init_context(chacha20_context *ctx, U8 *key, U8 *nonce, U64 counter) {
MemSet(ctx, 0, sizeof(chacha20_context));
chacha20_init_block(ctx, key, nonce);
chacha20_block_set_counter(ctx, counter);
ctx->counter = counter;
ctx->position = 64;
}
// XOR operation for ChaCha20
U0 chacha20_xor(chacha20_context *ctx, U8 *bytes, U64 n_bytes) {
U8 *keystream8 = ctx->keystream32(U8*);
// was U64 for some reason?
I64 i;
for (i = 0; i < n_bytes; i++) {
if (ctx->position >= 64) {
chacha20_block_next(ctx);
ctx->position = 0;
}
bytes[i] ^= keystream8[ctx->position++];
}
}
// Define key and nonce. Ensure they are the correct size (key: 32 bytes, nonce: 12 bytes).
U8 key[32] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
};
U8 nonce[12] = {
0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4A,
0x00, 0x00, 0x00, 0x00
};
U0 Main() {
I64 i;
// Define the plaintext message
U8 plaintext[16] = "Hello, TempleOS!";
U64 plaintext_len = sizeof(plaintext);
// Allocate space for the ciphertext (same size as plaintext)
U8 ciphertext[16];
// Initialize ChaCha20 context
chacha20_context ctx;
chacha20_init_context(&ctx, key, nonce, 0); // Counter starts at 0
// Encrypt the plaintext
MemCopy(ciphertext, plaintext, plaintext_len); // Copy plaintext to ciphertext buffer
chacha20_xor(&ctx, ciphertext, plaintext_len); // Perform XOR operation
// Output the encrypted message
"Encrypted Message: ";
for (i = 0; i < plaintext_len; i++) {
"%02X ", ciphertext[i];
}
"\n";
// Decrypt the ciphertext (same operation as encryption)
chacha20_init_context(&ctx, key, nonce, 0); // Reinitialize context for decryption
U8 decrypted[plaintext_len];
MemCopy(decrypted, ciphertext, plaintext_len); // Copy ciphertext to decrypted buffer
chacha20_xor(&ctx, decrypted, plaintext_len); // Perform XOR operation
// Output the decrypted message
"Decrypted Message: ";
for (i = 0; i < plaintext_len; i++) {
"%c", decrypted[i];
}
"\n";
}
Main;