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