diff options
author | Gary R Hook <gary.hook@amd.com> | 2018-03-07 12:31:14 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2018-03-16 11:35:52 -0400 |
commit | b698a9f4c5c52317db486b069190c7e3d2b97e7e (patch) | |
tree | 0395c4da367e027b2d2231c933c8096dc2a6de10 /drivers/crypto | |
parent | 3d053d53fcbe7343c89895bcfa2d6bc598740d55 (diff) |
crypto: ccp - Validate buffer lengths for copy operations
The CCP driver copies data between scatter/gather lists and DMA buffers.
The length of the requested copy operation must be checked against
the available destination buffer length.
Reported-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
Signed-off-by: Gary R Hook <gary.hook@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/ccp/ccp-ops.c | 108 |
1 files changed, 78 insertions, 30 deletions
diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c index 406b95329b3d..0ea43cdeb05f 100644 --- a/drivers/crypto/ccp/ccp-ops.c +++ b/drivers/crypto/ccp/ccp-ops.c | |||
@@ -178,14 +178,18 @@ static int ccp_init_dm_workarea(struct ccp_dm_workarea *wa, | |||
178 | return 0; | 178 | return 0; |
179 | } | 179 | } |
180 | 180 | ||
181 | static void ccp_set_dm_area(struct ccp_dm_workarea *wa, unsigned int wa_offset, | 181 | static int ccp_set_dm_area(struct ccp_dm_workarea *wa, unsigned int wa_offset, |
182 | struct scatterlist *sg, unsigned int sg_offset, | 182 | struct scatterlist *sg, unsigned int sg_offset, |
183 | unsigned int len) | 183 | unsigned int len) |
184 | { | 184 | { |
185 | WARN_ON(!wa->address); | 185 | WARN_ON(!wa->address); |
186 | 186 | ||
187 | if (len > (wa->length - wa_offset)) | ||
188 | return -EINVAL; | ||
189 | |||
187 | scatterwalk_map_and_copy(wa->address + wa_offset, sg, sg_offset, len, | 190 | scatterwalk_map_and_copy(wa->address + wa_offset, sg, sg_offset, len, |
188 | 0); | 191 | 0); |
192 | return 0; | ||
189 | } | 193 | } |
190 | 194 | ||
191 | static void ccp_get_dm_area(struct ccp_dm_workarea *wa, unsigned int wa_offset, | 195 | static void ccp_get_dm_area(struct ccp_dm_workarea *wa, unsigned int wa_offset, |
@@ -205,8 +209,11 @@ static int ccp_reverse_set_dm_area(struct ccp_dm_workarea *wa, | |||
205 | unsigned int len) | 209 | unsigned int len) |
206 | { | 210 | { |
207 | u8 *p, *q; | 211 | u8 *p, *q; |
212 | int rc; | ||
208 | 213 | ||
209 | ccp_set_dm_area(wa, wa_offset, sg, sg_offset, len); | 214 | rc = ccp_set_dm_area(wa, wa_offset, sg, sg_offset, len); |
215 | if (rc) | ||
216 | return rc; | ||
210 | 217 | ||
211 | p = wa->address + wa_offset; | 218 | p = wa->address + wa_offset; |
212 | q = p + len - 1; | 219 | q = p + len - 1; |
@@ -509,7 +516,9 @@ static int ccp_run_aes_cmac_cmd(struct ccp_cmd_queue *cmd_q, | |||
509 | return ret; | 516 | return ret; |
510 | 517 | ||
511 | dm_offset = CCP_SB_BYTES - aes->key_len; | 518 | dm_offset = CCP_SB_BYTES - aes->key_len; |
512 | ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len); | 519 | ret = ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len); |
520 | if (ret) | ||
521 | goto e_key; | ||
513 | ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, | 522 | ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, |
514 | CCP_PASSTHRU_BYTESWAP_256BIT); | 523 | CCP_PASSTHRU_BYTESWAP_256BIT); |
515 | if (ret) { | 524 | if (ret) { |
@@ -528,7 +537,9 @@ static int ccp_run_aes_cmac_cmd(struct ccp_cmd_queue *cmd_q, | |||
528 | goto e_key; | 537 | goto e_key; |
529 | 538 | ||
530 | dm_offset = CCP_SB_BYTES - AES_BLOCK_SIZE; | 539 | dm_offset = CCP_SB_BYTES - AES_BLOCK_SIZE; |
531 | ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); | 540 | ret = ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); |
541 | if (ret) | ||
542 | goto e_ctx; | ||
532 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, | 543 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, |
533 | CCP_PASSTHRU_BYTESWAP_256BIT); | 544 | CCP_PASSTHRU_BYTESWAP_256BIT); |
534 | if (ret) { | 545 | if (ret) { |
@@ -556,8 +567,10 @@ static int ccp_run_aes_cmac_cmd(struct ccp_cmd_queue *cmd_q, | |||
556 | goto e_src; | 567 | goto e_src; |
557 | } | 568 | } |
558 | 569 | ||
559 | ccp_set_dm_area(&ctx, 0, aes->cmac_key, 0, | 570 | ret = ccp_set_dm_area(&ctx, 0, aes->cmac_key, 0, |
560 | aes->cmac_key_len); | 571 | aes->cmac_key_len); |
572 | if (ret) | ||
573 | goto e_src; | ||
561 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, | 574 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, |
562 | CCP_PASSTHRU_BYTESWAP_256BIT); | 575 | CCP_PASSTHRU_BYTESWAP_256BIT); |
563 | if (ret) { | 576 | if (ret) { |
@@ -666,7 +679,9 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, | |||
666 | return ret; | 679 | return ret; |
667 | 680 | ||
668 | dm_offset = CCP_SB_BYTES - aes->key_len; | 681 | dm_offset = CCP_SB_BYTES - aes->key_len; |
669 | ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len); | 682 | ret = ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len); |
683 | if (ret) | ||
684 | goto e_key; | ||
670 | ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, | 685 | ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, |
671 | CCP_PASSTHRU_BYTESWAP_256BIT); | 686 | CCP_PASSTHRU_BYTESWAP_256BIT); |
672 | if (ret) { | 687 | if (ret) { |
@@ -685,7 +700,9 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, | |||
685 | goto e_key; | 700 | goto e_key; |
686 | 701 | ||
687 | dm_offset = CCP_AES_CTX_SB_COUNT * CCP_SB_BYTES - aes->iv_len; | 702 | dm_offset = CCP_AES_CTX_SB_COUNT * CCP_SB_BYTES - aes->iv_len; |
688 | ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); | 703 | ret = ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); |
704 | if (ret) | ||
705 | goto e_ctx; | ||
689 | 706 | ||
690 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, | 707 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, |
691 | CCP_PASSTHRU_BYTESWAP_256BIT); | 708 | CCP_PASSTHRU_BYTESWAP_256BIT); |
@@ -777,7 +794,9 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, | |||
777 | goto e_dst; | 794 | goto e_dst; |
778 | } | 795 | } |
779 | 796 | ||
780 | ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); | 797 | ret = ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); |
798 | if (ret) | ||
799 | goto e_dst; | ||
781 | 800 | ||
782 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, | 801 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, |
783 | CCP_PASSTHRU_BYTESWAP_256BIT); | 802 | CCP_PASSTHRU_BYTESWAP_256BIT); |
@@ -820,7 +839,9 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, | |||
820 | DMA_BIDIRECTIONAL); | 839 | DMA_BIDIRECTIONAL); |
821 | if (ret) | 840 | if (ret) |
822 | goto e_tag; | 841 | goto e_tag; |
823 | ccp_set_dm_area(&tag, 0, p_tag, 0, AES_BLOCK_SIZE); | 842 | ret = ccp_set_dm_area(&tag, 0, p_tag, 0, AES_BLOCK_SIZE); |
843 | if (ret) | ||
844 | goto e_tag; | ||
824 | 845 | ||
825 | ret = memcmp(tag.address, final_wa.address, AES_BLOCK_SIZE); | 846 | ret = memcmp(tag.address, final_wa.address, AES_BLOCK_SIZE); |
826 | ccp_dm_free(&tag); | 847 | ccp_dm_free(&tag); |
@@ -914,7 +935,9 @@ static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) | |||
914 | return ret; | 935 | return ret; |
915 | 936 | ||
916 | dm_offset = CCP_SB_BYTES - aes->key_len; | 937 | dm_offset = CCP_SB_BYTES - aes->key_len; |
917 | ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len); | 938 | ret = ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len); |
939 | if (ret) | ||
940 | goto e_key; | ||
918 | ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, | 941 | ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, |
919 | CCP_PASSTHRU_BYTESWAP_256BIT); | 942 | CCP_PASSTHRU_BYTESWAP_256BIT); |
920 | if (ret) { | 943 | if (ret) { |
@@ -935,7 +958,9 @@ static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) | |||
935 | if (aes->mode != CCP_AES_MODE_ECB) { | 958 | if (aes->mode != CCP_AES_MODE_ECB) { |
936 | /* Load the AES context - convert to LE */ | 959 | /* Load the AES context - convert to LE */ |
937 | dm_offset = CCP_SB_BYTES - AES_BLOCK_SIZE; | 960 | dm_offset = CCP_SB_BYTES - AES_BLOCK_SIZE; |
938 | ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); | 961 | ret = ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); |
962 | if (ret) | ||
963 | goto e_ctx; | ||
939 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, | 964 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, |
940 | CCP_PASSTHRU_BYTESWAP_256BIT); | 965 | CCP_PASSTHRU_BYTESWAP_256BIT); |
941 | if (ret) { | 966 | if (ret) { |
@@ -1113,8 +1138,12 @@ static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q, | |||
1113 | * big endian to little endian. | 1138 | * big endian to little endian. |
1114 | */ | 1139 | */ |
1115 | dm_offset = CCP_SB_BYTES - AES_KEYSIZE_128; | 1140 | dm_offset = CCP_SB_BYTES - AES_KEYSIZE_128; |
1116 | ccp_set_dm_area(&key, dm_offset, xts->key, 0, xts->key_len); | 1141 | ret = ccp_set_dm_area(&key, dm_offset, xts->key, 0, xts->key_len); |
1117 | ccp_set_dm_area(&key, 0, xts->key, xts->key_len, xts->key_len); | 1142 | if (ret) |
1143 | goto e_key; | ||
1144 | ret = ccp_set_dm_area(&key, 0, xts->key, xts->key_len, xts->key_len); | ||
1145 | if (ret) | ||
1146 | goto e_key; | ||
1118 | } else { | 1147 | } else { |
1119 | /* Version 5 CCPs use a 512-bit space for the key: each portion | 1148 | /* Version 5 CCPs use a 512-bit space for the key: each portion |
1120 | * occupies 256 bits, or one entire slot, and is zero-padded. | 1149 | * occupies 256 bits, or one entire slot, and is zero-padded. |
@@ -1123,9 +1152,13 @@ static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q, | |||
1123 | 1152 | ||
1124 | dm_offset = CCP_SB_BYTES; | 1153 | dm_offset = CCP_SB_BYTES; |
1125 | pad = dm_offset - xts->key_len; | 1154 | pad = dm_offset - xts->key_len; |
1126 | ccp_set_dm_area(&key, pad, xts->key, 0, xts->key_len); | 1155 | ret = ccp_set_dm_area(&key, pad, xts->key, 0, xts->key_len); |
1127 | ccp_set_dm_area(&key, dm_offset + pad, xts->key, xts->key_len, | 1156 | if (ret) |
1128 | xts->key_len); | 1157 | goto e_key; |
1158 | ret = ccp_set_dm_area(&key, dm_offset + pad, xts->key, | ||
1159 | xts->key_len, xts->key_len); | ||
1160 | if (ret) | ||
1161 | goto e_key; | ||
1129 | } | 1162 | } |
1130 | ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, | 1163 | ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, |
1131 | CCP_PASSTHRU_BYTESWAP_256BIT); | 1164 | CCP_PASSTHRU_BYTESWAP_256BIT); |
@@ -1144,7 +1177,9 @@ static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q, | |||
1144 | if (ret) | 1177 | if (ret) |
1145 | goto e_key; | 1178 | goto e_key; |
1146 | 1179 | ||
1147 | ccp_set_dm_area(&ctx, 0, xts->iv, 0, xts->iv_len); | 1180 | ret = ccp_set_dm_area(&ctx, 0, xts->iv, 0, xts->iv_len); |
1181 | if (ret) | ||
1182 | goto e_ctx; | ||
1148 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, | 1183 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, |
1149 | CCP_PASSTHRU_BYTESWAP_NOOP); | 1184 | CCP_PASSTHRU_BYTESWAP_NOOP); |
1150 | if (ret) { | 1185 | if (ret) { |
@@ -1287,12 +1322,18 @@ static int ccp_run_des3_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) | |||
1287 | dm_offset = CCP_SB_BYTES - des3->key_len; /* Basic offset */ | 1322 | dm_offset = CCP_SB_BYTES - des3->key_len; /* Basic offset */ |
1288 | 1323 | ||
1289 | len_singlekey = des3->key_len / 3; | 1324 | len_singlekey = des3->key_len / 3; |
1290 | ccp_set_dm_area(&key, dm_offset + 2 * len_singlekey, | 1325 | ret = ccp_set_dm_area(&key, dm_offset + 2 * len_singlekey, |
1291 | des3->key, 0, len_singlekey); | 1326 | des3->key, 0, len_singlekey); |
1292 | ccp_set_dm_area(&key, dm_offset + len_singlekey, | 1327 | if (ret) |
1293 | des3->key, len_singlekey, len_singlekey); | 1328 | goto e_key; |
1294 | ccp_set_dm_area(&key, dm_offset, | 1329 | ret = ccp_set_dm_area(&key, dm_offset + len_singlekey, |
1295 | des3->key, 2 * len_singlekey, len_singlekey); | 1330 | des3->key, len_singlekey, len_singlekey); |
1331 | if (ret) | ||
1332 | goto e_key; | ||
1333 | ret = ccp_set_dm_area(&key, dm_offset, | ||
1334 | des3->key, 2 * len_singlekey, len_singlekey); | ||
1335 | if (ret) | ||
1336 | goto e_key; | ||
1296 | 1337 | ||
1297 | /* Copy the key to the SB */ | 1338 | /* Copy the key to the SB */ |
1298 | ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, | 1339 | ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, |
@@ -1320,7 +1361,10 @@ static int ccp_run_des3_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) | |||
1320 | 1361 | ||
1321 | /* Load the context into the LSB */ | 1362 | /* Load the context into the LSB */ |
1322 | dm_offset = CCP_SB_BYTES - des3->iv_len; | 1363 | dm_offset = CCP_SB_BYTES - des3->iv_len; |
1323 | ccp_set_dm_area(&ctx, dm_offset, des3->iv, 0, des3->iv_len); | 1364 | ret = ccp_set_dm_area(&ctx, dm_offset, des3->iv, 0, |
1365 | des3->iv_len); | ||
1366 | if (ret) | ||
1367 | goto e_ctx; | ||
1324 | 1368 | ||
1325 | if (cmd_q->ccp->vdata->version == CCP_VERSION(3, 0)) | 1369 | if (cmd_q->ccp->vdata->version == CCP_VERSION(3, 0)) |
1326 | load_mode = CCP_PASSTHRU_BYTESWAP_NOOP; | 1370 | load_mode = CCP_PASSTHRU_BYTESWAP_NOOP; |
@@ -1604,8 +1648,10 @@ static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) | |||
1604 | } | 1648 | } |
1605 | } else { | 1649 | } else { |
1606 | /* Restore the context */ | 1650 | /* Restore the context */ |
1607 | ccp_set_dm_area(&ctx, 0, sha->ctx, 0, | 1651 | ret = ccp_set_dm_area(&ctx, 0, sha->ctx, 0, |
1608 | sb_count * CCP_SB_BYTES); | 1652 | sb_count * CCP_SB_BYTES); |
1653 | if (ret) | ||
1654 | goto e_ctx; | ||
1609 | } | 1655 | } |
1610 | 1656 | ||
1611 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, | 1657 | ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, |
@@ -1927,7 +1973,9 @@ static int ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q, | |||
1927 | if (ret) | 1973 | if (ret) |
1928 | return ret; | 1974 | return ret; |
1929 | 1975 | ||
1930 | ccp_set_dm_area(&mask, 0, pt->mask, 0, pt->mask_len); | 1976 | ret = ccp_set_dm_area(&mask, 0, pt->mask, 0, pt->mask_len); |
1977 | if (ret) | ||
1978 | goto e_mask; | ||
1931 | ret = ccp_copy_to_sb(cmd_q, &mask, op.jobid, op.sb_key, | 1979 | ret = ccp_copy_to_sb(cmd_q, &mask, op.jobid, op.sb_key, |
1932 | CCP_PASSTHRU_BYTESWAP_NOOP); | 1980 | CCP_PASSTHRU_BYTESWAP_NOOP); |
1933 | if (ret) { | 1981 | if (ret) { |