Skip to content

Commit e0aa9b3

Browse files
committed
perf: use prealloc Aes in encrypt/decrypt hot path (ue7.12)
Add wc_AesGcm_encrypt_sg_inplace_prealloc and wc_AesGcm_decrypt_sg_inplace_prealloc to wolfcrypt_glue.c/.h. These accept a pre-initialised Aes* instead of allocating one per call. The key schedule set at keypair creation time is reused by passing NULL key to wc_AesGcmEncryptInit/DecryptInit. Update send.c encrypt_packet and receive.c decrypt_packet to call the prealloc variants with the Aes fields embedded in noise_keypair (added in the preceding commit), eliminating the per-packet kmalloc/kfree of the Aes struct.
1 parent 8b667e4 commit e0aa9b3

4 files changed

Lines changed: 277 additions & 7 deletions

File tree

kernel-src/receive.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,9 @@ static bool decrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair)
301301
if (skb_to_sgvec(skb, sg, 0, skb->len) <= 0)
302302
return false;
303303

304-
if (! wc_AesGcm_decrypt_sg_inplace(sg, skb->len, NULL, 0,
305-
PACKET_CB(skb)->nonce,
306-
keypair->receiving.key,
307-
sizeof(keypair->receiving.key)))
304+
if (! wc_AesGcm_decrypt_sg_inplace_prealloc(sg, skb->len, NULL, 0,
305+
PACKET_CB(skb)->nonce,
306+
&keypair->aes_decrypt))
308307
return false;
309308

310309
/* Another ugly situation of pushing and pulling the header so as to

kernel-src/send.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,9 @@ static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair)
264264
if (skb_to_sgvec(skb, sg, sizeof(struct message_data),
265265
noise_encrypted_len(plaintext_len)) <= 0)
266266
return false;
267-
return wc_AesGcm_encrypt_sg_inplace(sg, plaintext_len, NULL, 0,
268-
PACKET_CB(skb)->nonce,
269-
keypair->sending.key, sizeof(keypair->sending.key));
267+
return wc_AesGcm_encrypt_sg_inplace_prealloc(sg, plaintext_len, NULL, 0,
268+
PACKET_CB(skb)->nonce,
269+
&keypair->aes_encrypt);
270270
}
271271

272272
void wg_packet_send_keepalive(struct wg_peer *peer)

kernel-src/wolfcrypt_glue.c

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,267 @@ bool wc_AesGcm_decrypt_sg_inplace(struct scatterlist *src, size_t src_len,
487487
ad, ad_len, nonce, key, key_len, 1));
488488
}
489489

490+
#ifdef WOLFSSL_AESGCM_STREAM
491+
492+
static __always_inline bool wc_AesGcm_crypt_sg_inplace_prealloc(
493+
struct scatterlist *src, const size_t src_len,
494+
const u8 *ad, const size_t ad_len,
495+
u64 nonce,
496+
Aes *aes,
497+
int isDecrypt)
498+
{
499+
int ret = -1;
500+
struct sg_mapping_iter miter;
501+
int miter_needs_stop = 0;
502+
unsigned int flags;
503+
ssize_t sl;
504+
byte full_nonce[AES_IV_SIZE];
505+
506+
if (WARN_ON((src_len > UINT_MAX) ||
507+
(ad_len > UINT_MAX)))
508+
{
509+
ret = -EINVAL;
510+
WC_DEBUG_PR_CODEPOINT();
511+
goto out;
512+
}
513+
514+
memset(full_nonce, 0, sizeof(full_nonce));
515+
#ifdef BIG_ENDIAN_ORDER
516+
nonce = cpu_to_le64(nonce);
517+
#endif
518+
memcpy(full_nonce + 4, (u8 *)&nonce, sizeof(nonce));
519+
520+
/* Pass NULL key: wc_AesGcmInit skips wc_AesGcmSetKey when key is NULL,
521+
* reusing the key schedule already set at keypair creation time.
522+
*/
523+
if (isDecrypt)
524+
ret = wc_AesGcmDecryptInit(aes, NULL, 0,
525+
full_nonce, (word32)sizeof(full_nonce));
526+
else
527+
ret = wc_AesGcmEncryptInit(aes, NULL, 0,
528+
full_nonce, (word32)sizeof(full_nonce));
529+
wc_ForceZero(full_nonce, sizeof full_nonce);
530+
if (ret != 0) {
531+
WC_DEBUG_PR_CODEPOINT();
532+
goto out;
533+
}
534+
535+
if (ad) {
536+
if (isDecrypt)
537+
ret = wc_AesGcmDecryptUpdate(aes, NULL, NULL,
538+
0, ad, ad_len);
539+
else
540+
ret = wc_AesGcmEncryptUpdate(aes, NULL, NULL,
541+
0, ad, ad_len);
542+
if (ret != 0) {
543+
WC_DEBUG_PR_CODEPOINT();
544+
goto out;
545+
}
546+
}
547+
548+
flags = SG_MITER_TO_SG | SG_MITER_ATOMIC;
549+
550+
sg_miter_start(&miter, src, sg_nents(src), flags);
551+
miter_needs_stop = 1;
552+
553+
for (sl = (ssize_t)src_len; sl > 0 && sg_miter_next(&miter); sl -= miter.length) {
554+
size_t length = min_t(size_t, sl, (ssize_t)miter.length);
555+
556+
if (isDecrypt)
557+
ret = wc_AesGcmDecryptUpdate(aes, miter.addr, miter.addr,
558+
length, NULL, 0);
559+
else
560+
ret = wc_AesGcmEncryptUpdate(aes, miter.addr, miter.addr,
561+
length, NULL, 0);
562+
if (ret != 0) {
563+
WC_DEBUG_PR_CODEPOINT();
564+
goto out;
565+
}
566+
}
567+
568+
if (sl <= -WC_AES_BLOCK_SIZE) {
569+
if (isDecrypt)
570+
ret = wc_AesGcmDecryptFinal(aes, miter.addr + (ssize_t)miter.length + sl, WC_AES_BLOCK_SIZE);
571+
else
572+
ret = wc_AesGcmEncryptFinal(aes, miter.addr + (ssize_t)miter.length + sl, WC_AES_BLOCK_SIZE);
573+
if (ret < 0) {
574+
WC_DEBUG_PR_CODEPOINT();
575+
goto out;
576+
}
577+
}
578+
579+
sg_miter_stop(&miter);
580+
miter_needs_stop = 0;
581+
582+
if (sl > -WC_AES_BLOCK_SIZE) {
583+
byte AuthTagBuf[WC_AES_BLOCK_SIZE];
584+
585+
if (isDecrypt) {
586+
scatterwalk_map_and_copy(AuthTagBuf, src, src_len,
587+
sizeof AuthTagBuf, 0 /* isEncrypt */);
588+
ret = wc_AesGcmDecryptFinal(aes, AuthTagBuf, WC_AES_BLOCK_SIZE);
589+
if (ret < 0)
590+
goto out;
591+
} else {
592+
ret = wc_AesGcmEncryptFinal(aes, AuthTagBuf, WC_AES_BLOCK_SIZE);
593+
if (ret < 0)
594+
goto out;
595+
scatterwalk_map_and_copy(AuthTagBuf, src, src_len,
596+
sizeof AuthTagBuf, 1 /* isEncrypt */);
597+
}
598+
}
599+
600+
ret = 0;
601+
602+
out:
603+
604+
if (miter_needs_stop)
605+
sg_miter_stop(&miter);
606+
607+
WC_DEBUG_PR_IF_NEG(ret);
608+
609+
return ret == 0;
610+
}
611+
612+
#else /* !WOLFSSL_AESGCM_STREAM */
613+
614+
static __always_inline bool wc_AesGcm_crypt_sg_inplace_prealloc(
615+
struct scatterlist *src, const size_t src_len,
616+
const u8 *ad, const size_t ad_len,
617+
u64 nonce,
618+
Aes *aes,
619+
int isDecrypt)
620+
{
621+
int ret = -1;
622+
struct sg_mapping_iter miter;
623+
unsigned int flags;
624+
byte full_nonce[AES_IV_SIZE];
625+
626+
if (WARN_ON((src_len > UINT_MAX) ||
627+
(ad_len > UINT_MAX)))
628+
{
629+
ret = -EINVAL;
630+
WC_DEBUG_PR_CODEPOINT();
631+
goto out;
632+
}
633+
634+
if (sg_nents(src) < 1) {
635+
ret = -EINVAL;
636+
WC_DEBUG_PR_CODEPOINT();
637+
goto out;
638+
}
639+
640+
memset(full_nonce, 0, sizeof(full_nonce));
641+
#ifdef BIG_ENDIAN_ORDER
642+
nonce = cpu_to_le64(nonce);
643+
#endif
644+
memcpy(full_nonce + 4, (u8 *)&nonce, sizeof(nonce));
645+
646+
flags = SG_MITER_TO_SG | SG_MITER_ATOMIC;
647+
648+
if (sg_nents(src) == 1) {
649+
size_t length;
650+
651+
sg_miter_start(&miter, src, sg_nents(src), flags);
652+
if ((sg_nents(src) == 1) && (! sg_miter_next(&miter))) {
653+
sg_miter_stop(&miter);
654+
ret = -EINVAL;
655+
WC_DEBUG_PR_CODEPOINT();
656+
goto out;
657+
}
658+
659+
if (miter.length < src_len + WC_AES_BLOCK_SIZE) {
660+
sg_miter_stop(&miter);
661+
goto copy_after_all;
662+
}
663+
664+
length = min_t(size_t, src_len, miter.length);
665+
666+
if (isDecrypt) {
667+
ret = wc_AesGcmDecrypt(aes, miter.addr,
668+
miter.addr, (word32)length,
669+
full_nonce, (word32)sizeof(full_nonce),
670+
miter.addr + length, WC_AES_BLOCK_SIZE,
671+
ad, (word32)ad_len);
672+
}
673+
else {
674+
ret = wc_AesGcmEncrypt(aes, miter.addr,
675+
miter.addr, (word32)length,
676+
full_nonce, (word32)sizeof(full_nonce),
677+
miter.addr + length, WC_AES_BLOCK_SIZE,
678+
ad, (word32)ad_len);
679+
}
680+
681+
sg_miter_stop(&miter);
682+
683+
goto out;
684+
}
685+
686+
copy_after_all:
687+
{
688+
byte *buf = (byte *)XMALLOC(src_len + WC_AES_BLOCK_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
689+
690+
if (! buf) {
691+
ret = -ENOMEM;
692+
WC_DEBUG_PR_CODEPOINT();
693+
goto out;
694+
}
695+
696+
if (isDecrypt) {
697+
scatterwalk_map_and_copy(buf, src, 0, src_len + WC_AES_BLOCK_SIZE, 0);
698+
ret = wc_AesGcmDecrypt(aes, buf,
699+
buf, (word32)src_len,
700+
full_nonce, (word32)sizeof(full_nonce),
701+
buf + src_len, WC_AES_BLOCK_SIZE,
702+
ad, (word32)ad_len);
703+
if (ret == 0)
704+
scatterwalk_map_and_copy(buf, src, 0, src_len, 1);
705+
wc_ForceZero(buf, src_len + WC_AES_BLOCK_SIZE);
706+
}
707+
else {
708+
scatterwalk_map_and_copy(buf, src, 0, src_len, 0);
709+
ret = wc_AesGcmEncrypt(aes, buf,
710+
buf, (word32)src_len,
711+
full_nonce, (word32)sizeof(full_nonce),
712+
buf + src_len, WC_AES_BLOCK_SIZE,
713+
ad, (word32)ad_len);
714+
if (ret == 0)
715+
scatterwalk_map_and_copy(buf, src, 0, src_len + WC_AES_BLOCK_SIZE, 1);
716+
else
717+
wc_ForceZero(buf, src_len + WC_AES_BLOCK_SIZE);
718+
}
719+
free(buf);
720+
}
721+
722+
out:
723+
724+
wc_ForceZero(full_nonce, sizeof full_nonce);
725+
726+
WC_DEBUG_PR_IF_NEG(ret);
727+
728+
return ret == 0;
729+
}
730+
731+
#endif /* !WOLFSSL_AESGCM_STREAM */
732+
733+
bool wc_AesGcm_encrypt_sg_inplace_prealloc(struct scatterlist *src, size_t src_len,
734+
const u8 *ad, const size_t ad_len,
735+
const u64 nonce,
736+
Aes *aes)
737+
{
738+
WC_DEBUG_PR_FALSE_RET(wc_AesGcm_crypt_sg_inplace_prealloc(src, src_len, ad, ad_len,
739+
nonce, aes, 0));
740+
}
741+
742+
bool wc_AesGcm_decrypt_sg_inplace_prealloc(struct scatterlist *src, size_t src_len,
743+
const u8 *ad, const size_t ad_len,
744+
const u64 nonce,
745+
Aes *aes)
746+
{
747+
WC_DEBUG_PR_FALSE_RET(wc_AesGcm_crypt_sg_inplace_prealloc(src, src_len - WC_AES_BLOCK_SIZE,
748+
ad, ad_len, nonce, aes, 1));
749+
}
750+
490751
int wc_ecc_make_keypair_exim(u8 *private, const size_t private_len,
491752
u8 *public, const size_t public_len,
492753
const int curve_id, int compressed)

kernel-src/wolfcrypt_glue.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,16 @@ extern bool wc_AesGcm_decrypt_sg_inplace(struct scatterlist *src, size_t src_len
215215
const u8 *key,
216216
const size_t key_len);
217217

218+
extern bool wc_AesGcm_encrypt_sg_inplace_prealloc(struct scatterlist *src, size_t src_len,
219+
const u8 *ad, const size_t ad_len,
220+
const u64 nonce,
221+
Aes *aes);
222+
223+
extern bool wc_AesGcm_decrypt_sg_inplace_prealloc(struct scatterlist *src, size_t src_len,
224+
const u8 *ad, const size_t ad_len,
225+
const u64 nonce,
226+
Aes *aes);
227+
218228
#ifdef WC_DRBG_BANKREF
219229

220230
extern struct wc_rng_bank *wc_wg_drbg;

0 commit comments

Comments
 (0)