| 795 | } |
| 796 | |
| 797 | static int |
| 798 | cryptodev_op(struct csession *cse, const struct crypt_op *cop) |
| 799 | { |
| 800 | struct cryptop_data *cod = NULL; |
| 801 | struct cryptop *crp = NULL; |
| 802 | char *dst; |
| 803 | int error; |
| 804 | |
| 805 | if (cop->len > 256*1024-4) { |
| 806 | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); |
| 807 | return (E2BIG); |
| 808 | } |
| 809 | |
| 810 | if (cse->txform) { |
| 811 | if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0) { |
| 812 | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); |
| 813 | return (EINVAL); |
| 814 | } |
| 815 | } |
| 816 | |
| 817 | if (cop->mac && cse->hashsize == 0) { |
| 818 | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); |
| 819 | return (EINVAL); |
| 820 | } |
| 821 | |
| 822 | /* |
| 823 | * The COP_F_CIPHER_FIRST flag predates explicit session |
| 824 | * modes, but the only way it was used was for EtA so allow it |
| 825 | * as long as it is consistent with EtA. |
| 826 | */ |
| 827 | if (cop->flags & COP_F_CIPHER_FIRST) { |
| 828 | if (cop->op != COP_ENCRYPT) { |
| 829 | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); |
| 830 | return (EINVAL); |
| 831 | } |
| 832 | } |
| 833 | |
| 834 | cod = cod_alloc(cse, 0, cop->len + cse->hashsize); |
| 835 | dst = cop->dst; |
| 836 | |
| 837 | crp = crypto_getreq(cse->cses, M_WAITOK); |
| 838 | |
| 839 | error = copyin(cop->src, cod->buf, cop->len); |
| 840 | if (error) { |
| 841 | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); |
| 842 | goto bail; |
| 843 | } |
| 844 | crp->crp_payload_start = 0; |
| 845 | crp->crp_payload_length = cop->len; |
| 846 | if (cse->hashsize) |
| 847 | crp->crp_digest_start = cop->len; |
| 848 | |
| 849 | switch (cse->mode) { |
| 850 | case CSP_MODE_COMPRESS: |
| 851 | switch (cop->op) { |
| 852 | case COP_ENCRYPT: |
| 853 | crp->crp_op = CRYPTO_OP_COMPRESS; |
| 854 | break; |
no test coverage detected