aboutsummaryrefslogtreecommitdiffstats
path: root/net/tls
diff options
context:
space:
mode:
authorVakul Garg <vakul.garg@nxp.com>2018-08-29 05:56:55 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-01 22:52:50 -0400
commit94524d8fc965a7a0facdef6d1b01d5ef6d71a802 (patch)
treee5624ee47fd2e1fbe03930af2df008fb511d6936 /net/tls
parent181ab62311c62fdd8c450969d0b822e1b89de42a (diff)
net/tls: Add support for async decryption of tls records
When tls records are decrypted using asynchronous acclerators such as NXP CAAM engine, the crypto apis return -EINPROGRESS. Presently, on getting -EINPROGRESS, the tls record processing stops till the time the crypto accelerator finishes off and returns the result. This incurs a context switch and is not an efficient way of accessing the crypto accelerators. Crypto accelerators work efficient when they are queued with multiple crypto jobs without having to wait for the previous ones to complete. The patch submits multiple crypto requests without having to wait for for previous ones to complete. This has been implemented for records which are decrypted in zero-copy mode. At the end of recvmsg(), we wait for all the asynchronous decryption requests to complete. The references to records which have been sent for async decryption are dropped. For cases where record decryption is not possible in zero-copy mode, asynchronous decryption is not used and we wait for decryption crypto api to complete. For crypto requests executing in async fashion, the memory for aead_request, sglists and skb etc is freed from the decryption completion handler. The decryption completion handler wakesup the sleeping user context when recvmsg() flags that it has done sending all the decryption requests and there are no more decryption requests pending to be completed. Signed-off-by: Vakul Garg <vakul.garg@nxp.com> Reviewed-by: Dave Watson <davejwatson@fb.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tls')
-rw-r--r--net/tls/tls_sw.c134
1 files changed, 121 insertions, 13 deletions
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 4ba62cd00a94..be4f2e990f9f 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -119,12 +119,50 @@ static int skb_nsg(struct sk_buff *skb, int offset, int len)
119 return __skb_nsg(skb, offset, len, 0); 119 return __skb_nsg(skb, offset, len, 0);
120} 120}
121 121
122static void tls_decrypt_done(struct crypto_async_request *req, int err)
123{
124 struct aead_request *aead_req = (struct aead_request *)req;
125 struct decrypt_req_ctx *req_ctx =
126 (struct decrypt_req_ctx *)(aead_req + 1);
127
128 struct scatterlist *sgout = aead_req->dst;
129
130 struct tls_context *tls_ctx = tls_get_ctx(req_ctx->sk);
131 struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
132 int pending = atomic_dec_return(&ctx->decrypt_pending);
133 struct scatterlist *sg;
134 unsigned int pages;
135
136 /* Propagate if there was an err */
137 if (err) {
138 ctx->async_wait.err = err;
139 tls_err_abort(req_ctx->sk, err);
140 }
141
142 /* Release the skb, pages and memory allocated for crypto req */
143 kfree_skb(req->data);
144
145 /* Skip the first S/G entry as it points to AAD */
146 for_each_sg(sg_next(sgout), sg, UINT_MAX, pages) {
147 if (!sg)
148 break;
149 put_page(sg_page(sg));
150 }
151
152 kfree(aead_req);
153
154 if (!pending && READ_ONCE(ctx->async_notify))
155 complete(&ctx->async_wait.completion);
156}
157
122static int tls_do_decryption(struct sock *sk, 158static int tls_do_decryption(struct sock *sk,
159 struct sk_buff *skb,
123 struct scatterlist *sgin, 160 struct scatterlist *sgin,
124 struct scatterlist *sgout, 161 struct scatterlist *sgout,
125 char *iv_recv, 162 char *iv_recv,
126 size_t data_len, 163 size_t data_len,
127 struct aead_request *aead_req) 164 struct aead_request *aead_req,
165 bool async)
128{ 166{
129 struct tls_context *tls_ctx = tls_get_ctx(sk); 167 struct tls_context *tls_ctx = tls_get_ctx(sk);
130 struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 168 struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
@@ -135,10 +173,34 @@ static int tls_do_decryption(struct sock *sk,
135 aead_request_set_crypt(aead_req, sgin, sgout, 173 aead_request_set_crypt(aead_req, sgin, sgout,
136 data_len + tls_ctx->rx.tag_size, 174 data_len + tls_ctx->rx.tag_size,
137 (u8 *)iv_recv); 175 (u8 *)iv_recv);
138 aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
139 crypto_req_done, &ctx->async_wait);
140 176
141 ret = crypto_wait_req(crypto_aead_decrypt(aead_req), &ctx->async_wait); 177 if (async) {
178 struct decrypt_req_ctx *req_ctx;
179
180 req_ctx = (struct decrypt_req_ctx *)(aead_req + 1);
181 req_ctx->sk = sk;
182
183 aead_request_set_callback(aead_req,
184 CRYPTO_TFM_REQ_MAY_BACKLOG,
185 tls_decrypt_done, skb);
186 atomic_inc(&ctx->decrypt_pending);
187 } else {
188 aead_request_set_callback(aead_req,
189 CRYPTO_TFM_REQ_MAY_BACKLOG,
190 crypto_req_done, &ctx->async_wait);
191 }
192
193 ret = crypto_aead_decrypt(aead_req);
194 if (ret == -EINPROGRESS) {
195 if (async)
196 return ret;
197
198 ret = crypto_wait_req(ret, &ctx->async_wait);
199 }
200
201 if (async)
202 atomic_dec(&ctx->decrypt_pending);
203
142 return ret; 204 return ret;
143} 205}
144 206
@@ -841,7 +903,10 @@ fallback_to_reg_recv:
841 } 903 }
842 904
843 /* Prepare and submit AEAD request */ 905 /* Prepare and submit AEAD request */
844 err = tls_do_decryption(sk, sgin, sgout, iv, data_len, aead_req); 906 err = tls_do_decryption(sk, skb, sgin, sgout, iv,
907 data_len, aead_req, *zc);
908 if (err == -EINPROGRESS)
909 return err;
845 910
846 /* Release the pages in case iov was mapped to pages */ 911 /* Release the pages in case iov was mapped to pages */
847 for (; pages > 0; pages--) 912 for (; pages > 0; pages--)
@@ -866,8 +931,12 @@ static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
866#endif 931#endif
867 if (!ctx->decrypted) { 932 if (!ctx->decrypted) {
868 err = decrypt_internal(sk, skb, dest, NULL, chunk, zc); 933 err = decrypt_internal(sk, skb, dest, NULL, chunk, zc);
869 if (err < 0) 934 if (err < 0) {
935 if (err == -EINPROGRESS)
936 tls_advance_record_sn(sk, &tls_ctx->rx);
937
870 return err; 938 return err;
939 }
871 } else { 940 } else {
872 *zc = false; 941 *zc = false;
873 } 942 }
@@ -895,18 +964,20 @@ static bool tls_sw_advance_skb(struct sock *sk, struct sk_buff *skb,
895{ 964{
896 struct tls_context *tls_ctx = tls_get_ctx(sk); 965 struct tls_context *tls_ctx = tls_get_ctx(sk);
897 struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); 966 struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
898 struct strp_msg *rxm = strp_msg(skb);
899 967
900 if (len < rxm->full_len) { 968 if (skb) {
901 rxm->offset += len; 969 struct strp_msg *rxm = strp_msg(skb);
902 rxm->full_len -= len;
903 970
904 return false; 971 if (len < rxm->full_len) {
972 rxm->offset += len;
973 rxm->full_len -= len;
974 return false;
975 }
976 kfree_skb(skb);
905 } 977 }
906 978
907 /* Finished with message */ 979 /* Finished with message */
908 ctx->recv_pkt = NULL; 980 ctx->recv_pkt = NULL;
909 kfree_skb(skb);
910 __strp_unpause(&ctx->strp); 981 __strp_unpause(&ctx->strp);
911 982
912 return true; 983 return true;
@@ -929,6 +1000,7 @@ int tls_sw_recvmsg(struct sock *sk,
929 int target, err = 0; 1000 int target, err = 0;
930 long timeo; 1001 long timeo;
931 bool is_kvec = msg->msg_iter.type & ITER_KVEC; 1002 bool is_kvec = msg->msg_iter.type & ITER_KVEC;
1003 int num_async = 0;
932 1004
933 flags |= nonblock; 1005 flags |= nonblock;
934 1006
@@ -941,6 +1013,7 @@ int tls_sw_recvmsg(struct sock *sk,
941 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); 1013 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
942 do { 1014 do {
943 bool zc = false; 1015 bool zc = false;
1016 bool async = false;
944 int chunk = 0; 1017 int chunk = 0;
945 1018
946 skb = tls_wait_data(sk, flags, timeo, &err); 1019 skb = tls_wait_data(sk, flags, timeo, &err);
@@ -948,6 +1021,7 @@ int tls_sw_recvmsg(struct sock *sk,
948 goto recv_end; 1021 goto recv_end;
949 1022
950 rxm = strp_msg(skb); 1023 rxm = strp_msg(skb);
1024
951 if (!cmsg) { 1025 if (!cmsg) {
952 int cerr; 1026 int cerr;
953 1027
@@ -974,26 +1048,39 @@ int tls_sw_recvmsg(struct sock *sk,
974 1048
975 err = decrypt_skb_update(sk, skb, &msg->msg_iter, 1049 err = decrypt_skb_update(sk, skb, &msg->msg_iter,
976 &chunk, &zc); 1050 &chunk, &zc);
977 if (err < 0) { 1051 if (err < 0 && err != -EINPROGRESS) {
978 tls_err_abort(sk, EBADMSG); 1052 tls_err_abort(sk, EBADMSG);
979 goto recv_end; 1053 goto recv_end;
980 } 1054 }
1055
1056 if (err == -EINPROGRESS) {
1057 async = true;
1058 num_async++;
1059 goto pick_next_record;
1060 }
1061
981 ctx->decrypted = true; 1062 ctx->decrypted = true;
982 } 1063 }
983 1064
984 if (!zc) { 1065 if (!zc) {
985 chunk = min_t(unsigned int, rxm->full_len, len); 1066 chunk = min_t(unsigned int, rxm->full_len, len);
1067
986 err = skb_copy_datagram_msg(skb, rxm->offset, msg, 1068 err = skb_copy_datagram_msg(skb, rxm->offset, msg,
987 chunk); 1069 chunk);
988 if (err < 0) 1070 if (err < 0)
989 goto recv_end; 1071 goto recv_end;
990 } 1072 }
991 1073
1074pick_next_record:
992 copied += chunk; 1075 copied += chunk;
993 len -= chunk; 1076 len -= chunk;
994 if (likely(!(flags & MSG_PEEK))) { 1077 if (likely(!(flags & MSG_PEEK))) {
995 u8 control = ctx->control; 1078 u8 control = ctx->control;
996 1079
1080 /* For async, drop current skb reference */
1081 if (async)
1082 skb = NULL;
1083
997 if (tls_sw_advance_skb(sk, skb, chunk)) { 1084 if (tls_sw_advance_skb(sk, skb, chunk)) {
998 /* Return full control message to 1085 /* Return full control message to
999 * userspace before trying to parse 1086 * userspace before trying to parse
@@ -1002,14 +1089,33 @@ int tls_sw_recvmsg(struct sock *sk,
1002 msg->msg_flags |= MSG_EOR; 1089 msg->msg_flags |= MSG_EOR;
1003 if (control != TLS_RECORD_TYPE_DATA) 1090 if (control != TLS_RECORD_TYPE_DATA)
1004 goto recv_end; 1091 goto recv_end;
1092 } else {
1093 break;
1005 } 1094 }
1006 } 1095 }
1096
1007 /* If we have a new message from strparser, continue now. */ 1097 /* If we have a new message from strparser, continue now. */
1008 if (copied >= target && !ctx->recv_pkt) 1098 if (copied >= target && !ctx->recv_pkt)
1009 break; 1099 break;
1010 } while (len); 1100 } while (len);
1011 1101
1012recv_end: 1102recv_end:
1103 if (num_async) {
1104 /* Wait for all previously submitted records to be decrypted */
1105 smp_store_mb(ctx->async_notify, true);
1106 if (atomic_read(&ctx->decrypt_pending)) {
1107 err = crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
1108 if (err) {
1109 /* one of async decrypt failed */
1110 tls_err_abort(sk, err);
1111 copied = 0;
1112 }
1113 } else {
1114 reinit_completion(&ctx->async_wait.completion);
1115 }
1116 WRITE_ONCE(ctx->async_notify, false);
1117 }
1118
1013 release_sock(sk); 1119 release_sock(sk);
1014 return copied ? : err; 1120 return copied ? : err;
1015} 1121}
@@ -1349,6 +1455,8 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
1349 goto free_aead; 1455 goto free_aead;
1350 1456
1351 if (sw_ctx_rx) { 1457 if (sw_ctx_rx) {
1458 (*aead)->reqsize = sizeof(struct decrypt_req_ctx);
1459
1352 /* Set up strparser */ 1460 /* Set up strparser */
1353 memset(&cb, 0, sizeof(cb)); 1461 memset(&cb, 0, sizeof(cb));
1354 cb.rcv_msg = tls_queue; 1462 cb.rcv_msg = tls_queue;