From 431319f30b026af4e7ec29adfe0542561d7d07a6 Mon Sep 17 00:00:00 2001 From: Tetsuya Yoshizaki Date: Sat, 17 Mar 2018 02:39:37 +0900 Subject: [PATCH 1/2] ltc: ctr: improve performance When accel_ctr_encrypt() is not used, accel_ecb_encrypt() is used via ecb_encrypt() instead. The accel_ecb_encrypt() is frequently called at every single block process. VFP assembly code called from the accel_ecb_encrypt() is protected by tomcrypt_arm_neon_enable()/disable(). FIQ enable/disable and VFP register save/restore (64bitx32 registers!) to/from memory are done in the tomcrypt_arm_neon_enable()/disable(). These overhead exist in each single block process cause the degradation of system performance eventually. Cases where h/w accelerated AES-CTR did not show any effects or showed less performance than pure software processing have been observed. This patch resolves the issue by increasing utilization rate of accel_ctr_encrypt(). Signed-off-by: Tetsuya Yoshizaki Signed-off-by: Victor Chong --- src/modes/ctr/ctr_encrypt.c | 91 ++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/src/modes/ctr/ctr_encrypt.c b/src/modes/ctr/ctr_encrypt.c index 7319cf53..af333d06 100644 --- a/src/modes/ctr/ctr_encrypt.c +++ b/src/modes/ctr/ctr_encrypt.c @@ -17,47 +17,17 @@ #ifdef LTC_CTR_MODE /** - CTR encrypt + CTR encrypt sub @param pt Plaintext @param ct [out] Ciphertext @param len Length of plaintext (octets) @param ctr CTR state @return CRYPT_OK if successful */ -int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) +static int ctr_encrypt_sub(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) { int x, err; - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(ctr != NULL); - - if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen/padlen valid? */ - if (ctr->blocklen < 1 || ctr->blocklen > (int)sizeof(ctr->ctr) || - ctr->padlen < 0 || ctr->padlen > (int)sizeof(ctr->pad)) { - return CRYPT_INVALID_ARG; - } - -#ifdef LTC_FAST - if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) { - return CRYPT_INVALID_ARG; - } -#endif - - /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */ - if ((ctr->padlen == ctr->blocklen) && cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL && (len >= (unsigned long)ctr->blocklen)) { - if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) { - return err; - } - pt += (len / ctr->blocklen) * ctr->blocklen; - ct += (len / ctr->blocklen) * ctr->blocklen; - len %= ctr->blocklen; - } - while (len) { /* is the pad empty? */ if (ctr->padlen == ctr->blocklen) { @@ -105,6 +75,63 @@ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s return CRYPT_OK; } +/** + CTR encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param ctr CTR state + @return CRYPT_OK if successful +*/ +int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) +{ + int err, fr; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ctr != NULL); + + if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (ctr->blocklen < 1 || ctr->blocklen > (int)sizeof(ctr->ctr) || + ctr->padlen < 0 || ctr->padlen > (int)sizeof(ctr->pad)) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */ + if (cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL && len >= (unsigned long)ctr->blocklen) { + if (ctr->padlen < ctr->blocklen) { + fr = ctr->blocklen - ctr->padlen; + if ((err = ctr_encrypt_sub(pt, ct, fr, ctr)) != CRYPT_OK) { + return err; + } + pt += fr; + ct += fr; + len -= fr; + } + + if (len >= (unsigned long)ctr->blocklen) { + if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) { + return err; + } + pt += (len / ctr->blocklen) * ctr->blocklen; + ct += (len / ctr->blocklen) * ctr->blocklen; + len %= ctr->blocklen; + } + } + + return ctr_encrypt_sub(pt, ct, len, ctr); +} + #endif /* ref: $Format:%D$ */ From bed9811d744424c6bc561aa84a3ed85892db7cf0 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Mon, 26 Mar 2018 23:34:15 +0200 Subject: [PATCH 2/2] fix-up ctr_encrypt.c --- src/modes/ctr/ctr_encrypt.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/modes/ctr/ctr_encrypt.c b/src/modes/ctr/ctr_encrypt.c index af333d06..eb7328c2 100644 --- a/src/modes/ctr/ctr_encrypt.c +++ b/src/modes/ctr/ctr_encrypt.c @@ -17,14 +17,14 @@ #ifdef LTC_CTR_MODE /** - CTR encrypt sub + CTR encrypt software implementation @param pt Plaintext @param ct [out] Ciphertext @param len Length of plaintext (octets) @param ctr CTR state @return CRYPT_OK if successful */ -static int ctr_encrypt_sub(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) +static int _ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) { int x, err; @@ -57,7 +57,7 @@ static int ctr_encrypt_sub(const unsigned char *pt, unsigned char *ct, unsigned ctr->padlen = 0; } #ifdef LTC_FAST - if (ctr->padlen == 0 && len >= (unsigned long)ctr->blocklen) { + if ((ctr->padlen == 0) && (len >= (unsigned long)ctr->blocklen)) { for (x = 0; x < ctr->blocklen; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) ^ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ctr->pad + x)); @@ -96,8 +96,8 @@ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s } /* is blocklen/padlen valid? */ - if (ctr->blocklen < 1 || ctr->blocklen > (int)sizeof(ctr->ctr) || - ctr->padlen < 0 || ctr->padlen > (int)sizeof(ctr->pad)) { + if ((ctr->blocklen < 1) || (ctr->blocklen > (int)sizeof(ctr->ctr)) || + (ctr->padlen < 0) || (ctr->padlen > (int)sizeof(ctr->pad))) { return CRYPT_INVALID_ARG; } @@ -108,11 +108,11 @@ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s #endif /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */ - if (cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL && len >= (unsigned long)ctr->blocklen) { + if ((cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL) && (len >= (unsigned long)ctr->blocklen)) { if (ctr->padlen < ctr->blocklen) { fr = ctr->blocklen - ctr->padlen; - if ((err = ctr_encrypt_sub(pt, ct, fr, ctr)) != CRYPT_OK) { - return err; + if ((err = _ctr_encrypt(pt, ct, fr, ctr)) != CRYPT_OK) { + return err; } pt += fr; ct += fr; @@ -121,7 +121,7 @@ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s if (len >= (unsigned long)ctr->blocklen) { if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) { - return err; + return err; } pt += (len / ctr->blocklen) * ctr->blocklen; ct += (len / ctr->blocklen) * ctr->blocklen; @@ -129,7 +129,7 @@ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s } } - return ctr_encrypt_sub(pt, ct, len, ctr); + return _ctr_encrypt(pt, ct, len, ctr); } #endif