| 1861 | } |
| 1862 | |
| 1863 | int __must_check |
| 1864 | ccp_gcm(struct ccp_queue *qp, struct ccp_session *s, struct cryptop *crp) |
| 1865 | { |
| 1866 | const struct crypto_session_params *csp; |
| 1867 | struct ccp_completion_ctx ctx; |
| 1868 | enum ccp_cipher_dir dir; |
| 1869 | device_t dev; |
| 1870 | unsigned i; |
| 1871 | int error; |
| 1872 | |
| 1873 | if (s->blkcipher.key_len == 0) |
| 1874 | return (EINVAL); |
| 1875 | |
| 1876 | dev = qp->cq_softc->dev; |
| 1877 | |
| 1878 | if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) |
| 1879 | dir = CCP_CIPHER_DIR_ENCRYPT; |
| 1880 | else |
| 1881 | dir = CCP_CIPHER_DIR_DECRYPT; |
| 1882 | |
| 1883 | /* Zero initial GHASH portion of context */ |
| 1884 | memset(s->blkcipher.iv, 0, sizeof(s->blkcipher.iv)); |
| 1885 | |
| 1886 | /* Gather IV data */ |
| 1887 | csp = crypto_get_params(crp->crp_session); |
| 1888 | ccp_collect_iv(crp, csp, s->blkcipher.iv); |
| 1889 | |
| 1890 | /* Reverse order of key material for HW */ |
| 1891 | ccp_byteswap(s->blkcipher.enckey, s->blkcipher.key_len); |
| 1892 | |
| 1893 | /* Prepare input buffer of concatenated lengths for final GHASH */ |
| 1894 | be64enc(s->gmac.final_block, (uint64_t)crp->crp_aad_length * 8); |
| 1895 | be64enc(&s->gmac.final_block[8], (uint64_t)crp->crp_payload_length * 8); |
| 1896 | |
| 1897 | /* Send IV + initial zero GHASH, key data, and lengths buffer to LSB */ |
| 1898 | error = ccp_do_pst_to_lsb(qp, ccp_queue_lsb_address(qp, LSB_ENTRY_IV), |
| 1899 | s->blkcipher.iv, 32); |
| 1900 | if (error != 0) |
| 1901 | return (error); |
| 1902 | error = ccp_do_pst_to_lsb(qp, ccp_queue_lsb_address(qp, LSB_ENTRY_KEY), |
| 1903 | s->blkcipher.enckey, s->blkcipher.key_len); |
| 1904 | if (error != 0) |
| 1905 | return (error); |
| 1906 | error = ccp_do_pst_to_lsb(qp, |
| 1907 | ccp_queue_lsb_address(qp, LSB_ENTRY_GHASH_IN), s->gmac.final_block, |
| 1908 | GMAC_BLOCK_LEN); |
| 1909 | if (error != 0) |
| 1910 | return (error); |
| 1911 | |
| 1912 | /* First step - compute GHASH over AAD */ |
| 1913 | if (crp->crp_aad_length != 0) { |
| 1914 | sglist_reset(qp->cq_sg_ulptx); |
| 1915 | error = sglist_append_sglist(qp->cq_sg_ulptx, qp->cq_sg_crp, |
| 1916 | crp->crp_aad_start, crp->crp_aad_length); |
| 1917 | if (error != 0) |
| 1918 | return (error); |
| 1919 | |
| 1920 | /* This engine cannot process non-block multiple AAD data. */ |
no test coverage detected