* SILC Crypto API for AES
*/
+/* CBC mode */
+
/* Sets the key for the cipher. */
-SILC_CIPHER_API_SET_KEY(aes)
+SILC_CIPHER_API_SET_KEY(aes_cbc)
{
- aes_encrypt_key(key, keylen, &((AesContext *)context)->enc);
- aes_decrypt_key(key, keylen, &((AesContext *)context)->dec);
+ if (encryption)
+ aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
+ else
+ aes_decrypt_key(key, keylen, &((AesContext *)context)->u.dec);
return TRUE;
}
+/* Sets IV for the cipher. */
+
+SILC_CIPHER_API_SET_IV(aes_cbc)
+{
+
+}
+
/* Returns the size of the cipher context. */
-SILC_CIPHER_API_CONTEXT_LEN(aes)
+SILC_CIPHER_API_CONTEXT_LEN(aes_cbc)
{
return sizeof(AesContext);
}
/* Encrypts with the cipher in CBC mode. Source and destination buffers
maybe one and same. */
-SILC_CIPHER_API_ENCRYPT_CBC(aes)
+SILC_CIPHER_API_ENCRYPT(aes_cbc)
{
int nb = len >> 4;
+ SILC_ASSERT((len & (16 - 1)) == 0);
+ if (len & (16 - 1))
+ return FALSE;
+
while(nb--) {
lp32(iv)[0] ^= lp32(src)[0];
lp32(iv)[1] ^= lp32(src)[1];
lp32(iv)[2] ^= lp32(src)[2];
lp32(iv)[3] ^= lp32(src)[3];
- aes_encrypt(iv, iv, &((AesContext *)context)->enc);
+ aes_encrypt(iv, iv, &((AesContext *)context)->u.enc);
memcpy(dst, iv, 16);
src += 16;
dst += 16;
/* Decrypts with the cipher in CBC mode. Source and destination buffers
maybe one and same. */
-SILC_CIPHER_API_DECRYPT_CBC(aes)
+SILC_CIPHER_API_DECRYPT(aes_cbc)
{
unsigned char tmp[16];
int nb = len >> 4;
+ if (len & (16 - 1))
+ return FALSE;
+
while(nb--) {
memcpy(tmp, src, 16);
- aes_decrypt(src, dst, &((AesContext *)context)->dec);
+ aes_decrypt(src, dst, &((AesContext *)context)->u.dec);
lp32(dst)[0] ^= lp32(iv)[0];
lp32(dst)[1] ^= lp32(iv)[1];
lp32(dst)[2] ^= lp32(iv)[2];
return TRUE;
}
+/* CTR mode */
+
+/* Sets the key for the cipher. */
+
+SILC_CIPHER_API_SET_KEY(aes_ctr)
+{
+ AesContext *aes = context;
+ memset(&aes->u.enc, 0, sizeof(aes->u.enc));
+ aes_encrypt_key(key, keylen, &aes->u.enc);
+ return TRUE;
+}
+
+/* Sets IV for the cipher. */
+
+SILC_CIPHER_API_SET_IV(aes_ctr)
+{
+ AesContext *aes = context;
+
+ /* Starts new block. */
+ aes->u.enc.inf.b[2] = 0;
+}
+
+/* Returns the size of the cipher context. */
+
+SILC_CIPHER_API_CONTEXT_LEN(aes_ctr)
+{
+ return sizeof(AesContext);
+}
+
+/* Encrypts with the cipher in CTR mode. Source and destination buffers
+ may be one and same. Assumes MSB first ordered counter. */
+
+SILC_CIPHER_API_ENCRYPT(aes_ctr)
+{
+ AesContext *aes = context;
+ SilcUInt32 ctr[4];
+ int i;
+
+ SILC_GET32_MSB(ctr[0], iv);
+ SILC_GET32_MSB(ctr[1], iv + 4);
+ SILC_GET32_MSB(ctr[2], iv + 8);
+ SILC_GET32_MSB(ctr[3], iv + 12);
+
+ i = aes->u.enc.inf.b[2];
+ if (!i)
+ i = 16;
+
+ while (len-- > 0) {
+ if (i == 16) {
+ if (++ctr[3] == 0)
+ if (++ctr[2] == 0)
+ if (++ctr[1] == 0)
+ ++ctr[0];
+
+ SILC_PUT32_MSB(ctr[0], iv);
+ SILC_PUT32_MSB(ctr[1], iv + 4);
+ SILC_PUT32_MSB(ctr[2], iv + 8);
+ SILC_PUT32_MSB(ctr[3], iv + 12);
+
+ aes_encrypt(iv, iv, &aes->u.enc);
+ i = 0;
+ }
+ *dst++ = *src++ ^ iv[i++];
+ }
+ aes->u.enc.inf.b[2] = i;
+
+ SILC_PUT32_MSB(ctr[0], iv);
+ SILC_PUT32_MSB(ctr[1], iv + 4);
+ SILC_PUT32_MSB(ctr[2], iv + 8);
+ SILC_PUT32_MSB(ctr[3], iv + 12);
+
+ return TRUE;
+}
+
+/* Decrypts with the cipher in CTR mode. Source and destination buffers
+ maybe one and same. */
+
+SILC_CIPHER_API_DECRYPT(aes_ctr)
+{
+ return silc_aes_ctr_encrypt(context, src, dst, len, iv);
+}
+
/****************************************************************************/
#if defined(__cplusplus)
#define d_4(t,n,b,e,f,g,h) ALIGN const XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) }
ALIGN const uint_32t t_dec(r,c)[RC_LENGTH] = rc_data(w0);
-#ifdef SILC_ASM_AES
+#ifdef SILC_AES_ASM
d_1(uint_8t, t_dec(i,box), isb_data, h0);
-#endif /* SILC_ASM_AES */
+#endif /* SILC_AES_ASM */
d_4(uint_32t, t_dec(f,n), sb_data, u0, u1, u2, u3);
d_4(uint_32t, t_dec(f,l), sb_data, w0, w1, w2, w3);
d_4(uint_32t, t_dec(i,n), isb_data, v0, v1, v2, v3);
}
}
-#ifndef SILC_ASM_AES
+#ifndef SILC_AES_ASM
/* C version of AES */
#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
}
#endif
-#endif /* SILC_ASM_AES */
+#endif /* SILC_AES_ASM */