1 1.6 riastrad /* $NetBSD: mvcesa.c,v 1.6 2022/05/22 11:39:27 riastradh Exp $ */ 2 1.1 kiyohara /* 3 1.1 kiyohara * Copyright (c) 2008 KIYOHARA Takashi 4 1.1 kiyohara * All rights reserved. 5 1.1 kiyohara * 6 1.1 kiyohara * Redistribution and use in source and binary forms, with or without 7 1.1 kiyohara * modification, are permitted provided that the following conditions 8 1.1 kiyohara * are met: 9 1.1 kiyohara * 1. Redistributions of source code must retain the above copyright 10 1.1 kiyohara * notice, this list of conditions and the following disclaimer. 11 1.1 kiyohara * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 kiyohara * notice, this list of conditions and the following disclaimer in the 13 1.1 kiyohara * documentation and/or other materials provided with the distribution. 14 1.1 kiyohara * 15 1.1 kiyohara * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 kiyohara * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 1.1 kiyohara * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 1.1 kiyohara * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 1.1 kiyohara * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 1.1 kiyohara * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 1.1 kiyohara * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 kiyohara * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 1.1 kiyohara * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 1.1 kiyohara * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 1.1 kiyohara * POSSIBILITY OF SUCH DAMAGE. 26 1.1 kiyohara */ 27 1.1 kiyohara 28 1.1 kiyohara #include <sys/cdefs.h> 29 1.6 riastrad __KERNEL_RCSID(0, "$NetBSD: mvcesa.c,v 1.6 2022/05/22 11:39:27 riastradh Exp $"); 30 1.1 kiyohara 31 1.1 kiyohara #include <sys/param.h> 32 1.1 kiyohara #include <sys/bus.h> 33 1.1 kiyohara #include <sys/cprng.h> 34 1.1 kiyohara #include <sys/device.h> 35 1.1 kiyohara #include <sys/endian.h> 36 1.1 kiyohara #include <sys/errno.h> 37 1.1 kiyohara #include <sys/mbuf.h> 38 1.1 kiyohara #include <sys/md5.h> 39 1.1 kiyohara #include <sys/uio.h> 40 1.1 kiyohara #include <sys/sha1.h> 41 1.1 kiyohara 42 1.1 kiyohara #include <opencrypto/cryptodev.h> 43 1.1 kiyohara #include <opencrypto/xform.h> 44 1.1 kiyohara 45 1.1 kiyohara #include <dev/marvell/marvellreg.h> 46 1.1 kiyohara #include <dev/marvell/marvellvar.h> 47 1.1 kiyohara #include <dev/marvell/mvcesareg.h> 48 1.1 kiyohara 49 1.1 kiyohara #include "locators.h" 50 1.1 kiyohara 51 1.1 kiyohara #define MVCESA_SESSION(sid) ((sid) & 0x0fffffff) 52 1.1 kiyohara #define MVCESA_SID(crd, sesn) (((crd) << 28) | ((sesn) & 0x0fffffff)) 53 1.1 kiyohara 54 1.1 kiyohara 55 1.1 kiyohara struct mvcesa_session { 56 1.1 kiyohara int ses_used; 57 1.1 kiyohara 58 1.1 kiyohara int ses_klen; 59 1.1 kiyohara uint32_t ses_key[8]; 60 1.1 kiyohara 61 1.1 kiyohara uint32_t ses_hminner[5]; /* HMAC inner state */ 62 1.1 kiyohara uint32_t ses_hmouter[5]; /* HMAC outer state */ 63 1.1 kiyohara }; 64 1.1 kiyohara 65 1.1 kiyohara struct mvcesa_softc { 66 1.1 kiyohara device_t sc_dev; 67 1.1 kiyohara 68 1.1 kiyohara bus_space_tag_t sc_iot; 69 1.1 kiyohara bus_space_handle_t sc_ioh; 70 1.1 kiyohara bus_dma_tag_t sc_dmat; 71 1.1 kiyohara 72 1.1 kiyohara int sc_cid; 73 1.1 kiyohara int sc_nsessions; 74 1.1 kiyohara struct mvcesa_session *sc_sessions; 75 1.1 kiyohara }; 76 1.1 kiyohara 77 1.1 kiyohara static int mvcesa_match(device_t, cfdata_t, void *); 78 1.1 kiyohara static void mvcesa_attach(device_t, device_t, void *); 79 1.1 kiyohara 80 1.1 kiyohara static int mvcesa_intr(void *); 81 1.1 kiyohara 82 1.1 kiyohara static int mvcesa_newsession(void *, u_int32_t *, struct cryptoini *); 83 1.6 riastrad static void mvcesa_freesession(void *, u_int64_t); 84 1.1 kiyohara static int mvcesa_process(void *, struct cryptop *, int); 85 1.1 kiyohara 86 1.1 kiyohara static int mvcesa_authentication(struct mvcesa_softc *, struct mvcesa_session *, 87 1.1 kiyohara uint32_t, uint32_t *, uint32_t *, uint64_t, 88 1.1 kiyohara int, int, char *, struct mbuf *, struct uio *); 89 1.1 kiyohara static int mvcesa_des_encdec(struct mvcesa_softc *, struct mvcesa_session *, 90 1.1 kiyohara uint32_t, uint32_t, uint32_t, uint32_t *, int, int, 91 1.1 kiyohara char *, struct mbuf *, struct uio *); 92 1.1 kiyohara 93 1.1 kiyohara 94 1.1 kiyohara CFATTACH_DECL_NEW(mvcesa_gt, sizeof(struct mvcesa_softc), 95 1.1 kiyohara mvcesa_match, mvcesa_attach, NULL, NULL); 96 1.1 kiyohara CFATTACH_DECL_NEW(mvcesa_mbus, sizeof(struct mvcesa_softc), 97 1.1 kiyohara mvcesa_match, mvcesa_attach, NULL, NULL); 98 1.1 kiyohara 99 1.1 kiyohara 100 1.1 kiyohara /* ARGSUSED */ 101 1.1 kiyohara static int 102 1.1 kiyohara mvcesa_match(device_t parent, cfdata_t match, void *aux) 103 1.1 kiyohara { 104 1.1 kiyohara struct marvell_attach_args *mva = aux; 105 1.1 kiyohara 106 1.1 kiyohara if (strcmp(mva->mva_name, match->cf_name) != 0) 107 1.1 kiyohara return 0; 108 1.1 kiyohara if (mva->mva_offset == MVA_OFFSET_DEFAULT || 109 1.1 kiyohara mva->mva_irq == MVA_IRQ_DEFAULT) 110 1.1 kiyohara return 0; 111 1.1 kiyohara 112 1.1 kiyohara mva->mva_size = MVCESA_SIZE; 113 1.1 kiyohara return 1; 114 1.1 kiyohara } 115 1.1 kiyohara 116 1.1 kiyohara /* ARGSUSED */ 117 1.1 kiyohara static void 118 1.1 kiyohara mvcesa_attach(device_t parent, device_t self, void *aux) 119 1.1 kiyohara { 120 1.1 kiyohara struct mvcesa_softc *sc = device_private(self); 121 1.1 kiyohara struct marvell_attach_args *mva = aux; 122 1.1 kiyohara 123 1.1 kiyohara aprint_normal( 124 1.1 kiyohara ": Marvell Cryptographic Engines and Security Accelerator\n"); 125 1.1 kiyohara aprint_naive("\n"); 126 1.1 kiyohara 127 1.1 kiyohara sc->sc_dev = self; 128 1.1 kiyohara sc->sc_iot = mva->mva_iot; 129 1.1 kiyohara /* Map I/O registers */ 130 1.1 kiyohara if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, mva->mva_offset, 131 1.1 kiyohara mva->mva_size, &sc->sc_ioh)) { 132 1.1 kiyohara aprint_error_dev(self, "can't map registers\n"); 133 1.1 kiyohara return; 134 1.1 kiyohara } 135 1.1 kiyohara sc->sc_dmat = mva->mva_dmat; 136 1.1 kiyohara 137 1.1 kiyohara sc->sc_nsessions = 0; 138 1.1 kiyohara 139 1.1 kiyohara /* Setup Opencrypto stuff */ 140 1.1 kiyohara sc->sc_cid = crypto_get_driverid(0); 141 1.1 kiyohara if (sc->sc_cid < 0) { 142 1.1 kiyohara aprint_error_dev(self, "couldn't get crypto driver id\n"); 143 1.1 kiyohara return; 144 1.1 kiyohara } 145 1.1 kiyohara crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0, 146 1.1 kiyohara mvcesa_newsession, mvcesa_freesession, mvcesa_process, sc); 147 1.1 kiyohara crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0, 148 1.1 kiyohara mvcesa_newsession, mvcesa_freesession, mvcesa_process, sc); 149 1.1 kiyohara #if __DMA_notyet__ 150 1.1 kiyohara /* 151 1.1 kiyohara * Don't know how to process to AES CBC in PIO-mode. 152 1.1 kiyohara * I havn't found IV registers. 153 1.1 kiyohara */ 154 1.1 kiyohara crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0, 155 1.1 kiyohara mvcesa_newsession, mvcesa_freesession, mvcesa_process, sc); 156 1.1 kiyohara #endif 157 1.1 kiyohara crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0, 158 1.1 kiyohara mvcesa_newsession, mvcesa_freesession, mvcesa_process, sc); 159 1.1 kiyohara crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0, 160 1.1 kiyohara mvcesa_newsession, mvcesa_freesession, mvcesa_process, sc); 161 1.1 kiyohara crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0, 162 1.1 kiyohara mvcesa_newsession, mvcesa_freesession, mvcesa_process, sc); 163 1.1 kiyohara crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0, 164 1.1 kiyohara mvcesa_newsession, mvcesa_freesession, mvcesa_process, sc); 165 1.1 kiyohara 166 1.1 kiyohara /* Clear and establish interrupt */ 167 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_IC, 0); 168 1.1 kiyohara marvell_intr_establish(mva->mva_irq, IPL_NET, mvcesa_intr, sc); 169 1.1 kiyohara 170 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_IM, 0); 171 1.1 kiyohara } 172 1.1 kiyohara 173 1.1 kiyohara 174 1.1 kiyohara static int 175 1.1 kiyohara mvcesa_intr(void *arg) 176 1.1 kiyohara { 177 1.1 kiyohara #if 0 178 1.1 kiyohara struct mvcesa_softc *sc = (struct mvcesa_softc *)arg; 179 1.1 kiyohara #endif 180 1.1 kiyohara int handled = 0; 181 1.1 kiyohara 182 1.1 kiyohara return handled; 183 1.1 kiyohara } 184 1.1 kiyohara 185 1.1 kiyohara 186 1.1 kiyohara /* 187 1.1 kiyohara * Opencrypto functions 188 1.1 kiyohara */ 189 1.1 kiyohara /* 190 1.1 kiyohara * Allocate a new 'session' and return an encoded session id. 'sidp' 191 1.1 kiyohara * contains our registration id, and should contain an encoded session 192 1.1 kiyohara * id on successful allocation. 193 1.1 kiyohara */ 194 1.1 kiyohara static int 195 1.1 kiyohara mvcesa_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri) 196 1.1 kiyohara { 197 1.1 kiyohara struct mvcesa_softc *sc = (struct mvcesa_softc *)arg; 198 1.1 kiyohara struct cryptoini *c; 199 1.1 kiyohara struct mvcesa_session *ses = NULL; 200 1.1 kiyohara int sesn, count, enc, mac, i; 201 1.1 kiyohara 202 1.1 kiyohara KASSERT(sc != NULL /*, ("mvcesa_newsession: null softc")*/); 203 1.1 kiyohara if (sidp == NULL || cri == NULL || sc == NULL) 204 1.1 kiyohara return EINVAL; 205 1.1 kiyohara 206 1.1 kiyohara for (sesn = 0; sesn < sc->sc_nsessions; sesn++) 207 1.1 kiyohara if (sc->sc_sessions[sesn].ses_used == 0) { 208 1.1 kiyohara ses = sc->sc_sessions + sesn; 209 1.1 kiyohara break; 210 1.1 kiyohara } 211 1.1 kiyohara 212 1.1 kiyohara if (ses == NULL) { 213 1.1 kiyohara sesn = sc->sc_nsessions; 214 1.1 kiyohara ses = malloc((sesn + 1) * sizeof(*ses), M_DEVBUF, M_NOWAIT); 215 1.1 kiyohara if (ses == NULL) 216 1.1 kiyohara return ENOMEM; 217 1.1 kiyohara if (sesn != 0) { 218 1.1 kiyohara memcpy(ses, sc->sc_sessions, sesn * sizeof(*ses)); 219 1.1 kiyohara memset(sc->sc_sessions, 0, sesn * sizeof(*ses)); 220 1.1 kiyohara free(sc->sc_sessions, M_DEVBUF); 221 1.1 kiyohara } 222 1.1 kiyohara sc->sc_sessions = ses; 223 1.1 kiyohara ses = sc->sc_sessions + sesn; 224 1.1 kiyohara sc->sc_nsessions++; 225 1.1 kiyohara } 226 1.1 kiyohara memset(ses, 0, sizeof(*ses)); 227 1.1 kiyohara 228 1.1 kiyohara count = 0; 229 1.1 kiyohara enc = mac = 0; 230 1.1 kiyohara for (c = cri; c != NULL; c = c->cri_next) { 231 1.1 kiyohara switch (c->cri_alg) { 232 1.1 kiyohara case CRYPTO_DES_CBC: 233 1.1 kiyohara case CRYPTO_3DES_CBC: 234 1.1 kiyohara if (enc) 235 1.1 kiyohara return EINVAL; 236 1.1 kiyohara enc = 1; 237 1.1 kiyohara 238 1.1 kiyohara /* Go ahead and compute key in CESA's byte order */ 239 1.1 kiyohara ses->ses_klen = c->cri_klen; 240 1.1 kiyohara memcpy(ses->ses_key, c->cri_key, c->cri_klen / 8); 241 1.1 kiyohara switch (c->cri_alg) { 242 1.1 kiyohara case CRYPTO_3DES_CBC: 243 1.1 kiyohara ses->ses_key[5] = htobe32(ses->ses_key[5]); 244 1.1 kiyohara ses->ses_key[4] = htobe32(ses->ses_key[4]); 245 1.1 kiyohara ses->ses_key[3] = htobe32(ses->ses_key[3]); 246 1.1 kiyohara ses->ses_key[2] = htobe32(ses->ses_key[2]); 247 1.1 kiyohara 248 1.1 kiyohara /* FALLTHROUGH */ 249 1.1 kiyohara case CRYPTO_DES_CBC: 250 1.1 kiyohara ses->ses_key[1] = htobe32(ses->ses_key[1]); 251 1.1 kiyohara ses->ses_key[0] = htobe32(ses->ses_key[0]); 252 1.1 kiyohara } 253 1.1 kiyohara break; 254 1.1 kiyohara 255 1.1 kiyohara case CRYPTO_SHA1_HMAC: 256 1.1 kiyohara case CRYPTO_MD5_HMAC: 257 1.1 kiyohara { 258 1.1 kiyohara MD5_CTX md5ctx; 259 1.1 kiyohara SHA1_CTX sha1ctx; 260 1.1 kiyohara int klen_bytes = c->cri_klen / 8; 261 1.1 kiyohara 262 1.1 kiyohara KASSERT(c->cri_klen == 512); 263 1.1 kiyohara 264 1.1 kiyohara for (i = 0; i < klen_bytes; i++) 265 1.1 kiyohara c->cri_key[i] ^= HMAC_IPAD_VAL; 266 1.1 kiyohara if (c->cri_alg == CRYPTO_MD5_HMAC_96) { 267 1.1 kiyohara MD5Init(&md5ctx); 268 1.1 kiyohara MD5Update(&md5ctx, c->cri_key, klen_bytes); 269 1.1 kiyohara MD5Update(&md5ctx, hmac_ipad_buffer, 270 1.1 kiyohara HMAC_BLOCK_LEN - klen_bytes); 271 1.1 kiyohara memcpy(ses->ses_hminner, md5ctx.state, 272 1.1 kiyohara sizeof(md5ctx.state)); 273 1.1 kiyohara } else { 274 1.1 kiyohara SHA1Init(&sha1ctx); 275 1.1 kiyohara SHA1Update(&sha1ctx, c->cri_key, klen_bytes); 276 1.1 kiyohara SHA1Update(&sha1ctx, hmac_ipad_buffer, 277 1.1 kiyohara HMAC_BLOCK_LEN - klen_bytes); 278 1.1 kiyohara memcpy(ses->ses_hminner, sha1ctx.state, 279 1.1 kiyohara sizeof(sha1ctx.state)); 280 1.1 kiyohara } 281 1.1 kiyohara 282 1.1 kiyohara for (i = 0; i < klen_bytes; i++) 283 1.1 kiyohara c->cri_key[i] ^= 284 1.1 kiyohara (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 285 1.1 kiyohara if (c->cri_alg == CRYPTO_MD5_HMAC_96) { 286 1.1 kiyohara MD5Init(&md5ctx); 287 1.1 kiyohara MD5Update(&md5ctx, c->cri_key, klen_bytes); 288 1.1 kiyohara MD5Update(&md5ctx, hmac_opad_buffer, 289 1.1 kiyohara HMAC_BLOCK_LEN - klen_bytes); 290 1.1 kiyohara memcpy(ses->ses_hmouter, md5ctx.state, 291 1.1 kiyohara sizeof(md5ctx.state)); 292 1.1 kiyohara } else { 293 1.1 kiyohara SHA1Init(&sha1ctx); 294 1.1 kiyohara SHA1Update(&sha1ctx, c->cri_key, klen_bytes); 295 1.1 kiyohara SHA1Update(&sha1ctx, hmac_opad_buffer, 296 1.1 kiyohara HMAC_BLOCK_LEN - klen_bytes); 297 1.1 kiyohara memcpy(ses->ses_hmouter, sha1ctx.state, 298 1.1 kiyohara sizeof(sha1ctx.state)); 299 1.1 kiyohara } 300 1.1 kiyohara 301 1.1 kiyohara for (i = 0; i < klen_bytes; i++) 302 1.1 kiyohara c->cri_key[i] ^= HMAC_OPAD_VAL; 303 1.1 kiyohara } 304 1.1 kiyohara /* FALLTHROUGH */ 305 1.1 kiyohara 306 1.1 kiyohara case CRYPTO_SHA1: 307 1.1 kiyohara case CRYPTO_MD5: 308 1.1 kiyohara if (mac) 309 1.1 kiyohara return EINVAL; 310 1.1 kiyohara mac = 1; 311 1.1 kiyohara } 312 1.1 kiyohara count++; 313 1.1 kiyohara } 314 1.1 kiyohara if (count > 2) { 315 1.1 kiyohara mvcesa_freesession(sc, sesn); 316 1.1 kiyohara return EINVAL; 317 1.1 kiyohara } 318 1.1 kiyohara 319 1.1 kiyohara *sidp = MVCESA_SID(device_unit(sc->sc_dev), sesn); 320 1.1 kiyohara ses->ses_used = 1; 321 1.1 kiyohara 322 1.1 kiyohara return 0; 323 1.1 kiyohara } 324 1.1 kiyohara 325 1.1 kiyohara /* 326 1.1 kiyohara * Deallocate a session. 327 1.1 kiyohara */ 328 1.6 riastrad static void 329 1.1 kiyohara mvcesa_freesession(void *arg, u_int64_t tid) 330 1.1 kiyohara { 331 1.1 kiyohara struct mvcesa_softc *sc = (struct mvcesa_softc *)arg; 332 1.1 kiyohara int session; 333 1.1 kiyohara uint32_t sid = ((uint32_t)tid) & 0xffffffff; 334 1.1 kiyohara 335 1.1 kiyohara session = MVCESA_SESSION(sid); 336 1.5 riastrad KASSERTMSG(session >= 0, "session=%d", session); 337 1.5 riastrad KASSERTMSG(session < sc->sc_nsessions, "session=%d nsessions=%d", 338 1.5 riastrad session, sc->sc_nsessions); 339 1.1 kiyohara 340 1.1 kiyohara memset(&sc->sc_sessions[session], 0, sizeof(sc->sc_sessions[session])); 341 1.1 kiyohara } 342 1.1 kiyohara 343 1.1 kiyohara static int 344 1.1 kiyohara mvcesa_process(void *arg, struct cryptop *crp, int hint) 345 1.1 kiyohara { 346 1.5 riastrad struct mvcesa_softc *sc = arg; 347 1.1 kiyohara struct mvcesa_session *ses; 348 1.1 kiyohara struct cryptodesc *crd; 349 1.1 kiyohara struct mbuf *m = NULL; 350 1.1 kiyohara struct uio *uio = NULL; 351 1.1 kiyohara int session; 352 1.1 kiyohara char *buf = NULL; 353 1.1 kiyohara 354 1.1 kiyohara session = MVCESA_SESSION(crp->crp_sid); 355 1.5 riastrad KASSERTMSG(session < sc->sc_nsessions, "session=%d nsessions=%d", 356 1.5 riastrad session, sc->sc_nsessions); 357 1.1 kiyohara ses = &sc->sc_sessions[session]; 358 1.1 kiyohara 359 1.1 kiyohara if (crp->crp_flags & CRYPTO_F_IMBUF) 360 1.1 kiyohara m = (struct mbuf *)crp->crp_buf; 361 1.1 kiyohara else if (crp->crp_flags & CRYPTO_F_IOV) 362 1.1 kiyohara uio = (struct uio *)crp->crp_buf; 363 1.1 kiyohara else 364 1.1 kiyohara buf = (char *)crp->crp_buf; 365 1.1 kiyohara 366 1.1 kiyohara if (0 /* DMA support */) { 367 1.1 kiyohara /* not yet... */ 368 1.1 kiyohara 369 1.1 kiyohara goto done; 370 1.1 kiyohara } 371 1.1 kiyohara 372 1.1 kiyohara /* PIO operation */ 373 1.1 kiyohara 374 1.1 kiyohara for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 375 1.1 kiyohara switch (crd->crd_alg) { 376 1.1 kiyohara case CRYPTO_DES_CBC: 377 1.1 kiyohara case CRYPTO_3DES_CBC: 378 1.1 kiyohara { 379 1.1 kiyohara uint32_t alg, mode, dir, *iv, ivbuf[2]; 380 1.1 kiyohara 381 1.1 kiyohara mode = MVCESA_DESE_C_DESMODE_CBC; 382 1.1 kiyohara if (crd->crd_alg == CRYPTO_DES_CBC) 383 1.1 kiyohara alg = MVCESA_DESE_C_ALGORITHM_DES; 384 1.1 kiyohara else { /* CRYPTO_3DES_CBC */ 385 1.1 kiyohara alg = MVCESA_DESE_C_ALGORITHM_3DES; 386 1.1 kiyohara mode |= MVCESA_DESE_C_3DESMODE_EDE; 387 1.1 kiyohara } 388 1.1 kiyohara if (crd->crd_flags & CRD_F_ENCRYPT) { 389 1.1 kiyohara dir = MVCESA_DESE_C_DIRECTION_ENC; 390 1.1 kiyohara if (crd->crd_flags & CRD_F_IV_EXPLICIT) 391 1.1 kiyohara iv = (uint32_t *)crd->crd_iv; 392 1.3 riastrad else { 393 1.3 riastrad cprng_fast(ivbuf, sizeof(ivbuf)); 394 1.3 riastrad iv = ivbuf; 395 1.3 riastrad } 396 1.1 kiyohara if (!(crd->crd_flags & CRD_F_IV_PRESENT)) { 397 1.1 kiyohara if (m != NULL) 398 1.1 kiyohara m_copyback(m, crd->crd_inject, 399 1.1 kiyohara 8, iv); 400 1.1 kiyohara else if (uio != NULL) 401 1.1 kiyohara cuio_copyback(uio, 402 1.1 kiyohara crd->crd_inject, 8, iv); 403 1.1 kiyohara } 404 1.1 kiyohara } else { 405 1.1 kiyohara dir = MVCESA_DESE_C_DIRECTION_DEC; 406 1.1 kiyohara if (crd->crd_flags & CRD_F_IV_EXPLICIT) 407 1.1 kiyohara iv = (uint32_t *)crd->crd_iv; 408 1.1 kiyohara else { 409 1.1 kiyohara if (m != NULL) 410 1.1 kiyohara m_copydata(m, crd->crd_inject, 411 1.1 kiyohara 8, ivbuf); 412 1.1 kiyohara else if (uio != NULL) 413 1.1 kiyohara cuio_copydata(uio, 414 1.1 kiyohara crd->crd_inject, 8, ivbuf); 415 1.1 kiyohara iv = ivbuf; 416 1.1 kiyohara } 417 1.1 kiyohara } 418 1.1 kiyohara 419 1.1 kiyohara crp->crp_etype = mvcesa_des_encdec(sc, ses, 420 1.1 kiyohara alg, mode, dir, iv, crd->crd_skip, crd->crd_len, 421 1.1 kiyohara buf, m, uio); 422 1.1 kiyohara break; 423 1.1 kiyohara } 424 1.1 kiyohara 425 1.1 kiyohara case CRYPTO_SHA1: 426 1.1 kiyohara case CRYPTO_SHA1_HMAC: 427 1.1 kiyohara case CRYPTO_MD5: 428 1.1 kiyohara case CRYPTO_MD5_HMAC: 429 1.1 kiyohara { 430 1.1 kiyohara uint64_t bits; 431 1.1 kiyohara uint32_t alg, *iv = NULL, digest[512 / 8 / 4], dlen; 432 1.1 kiyohara 433 1.1 kiyohara if (crd->crd_alg == CRYPTO_SHA1 || 434 1.1 kiyohara crd->crd_alg == CRYPTO_SHA1_HMAC) { 435 1.1 kiyohara alg = MVCESA_SHA1MD5I_AC_ALGORITHM_SHA1; 436 1.1 kiyohara dlen = 160; 437 1.1 kiyohara } else { /* CRYPTO_MD5 || CRYPTO_MD5_HMAC */ 438 1.1 kiyohara alg = MVCESA_SHA1MD5I_AC_ALGORITHM_MD5; 439 1.1 kiyohara dlen = 128; 440 1.1 kiyohara } 441 1.1 kiyohara bits = crd->crd_len << 3; 442 1.1 kiyohara if (crd->crd_alg == CRYPTO_SHA1_HMAC || 443 1.1 kiyohara crd->crd_alg == CRYPTO_MD5_HMAC) { 444 1.1 kiyohara iv = ses->ses_hminner; 445 1.1 kiyohara bits += 512; 446 1.1 kiyohara } 447 1.1 kiyohara 448 1.1 kiyohara crp->crp_etype = mvcesa_authentication(sc, ses, 449 1.1 kiyohara alg, iv, digest, bits, crd->crd_skip, crd->crd_len, 450 1.1 kiyohara buf, m, uio); 451 1.1 kiyohara if (crp->crp_etype != 0) 452 1.1 kiyohara break; 453 1.1 kiyohara 454 1.1 kiyohara if (crd->crd_alg == CRYPTO_SHA1_HMAC || 455 1.1 kiyohara crd->crd_alg == CRYPTO_MD5_HMAC) 456 1.1 kiyohara crp->crp_etype = mvcesa_authentication(sc, 457 1.1 kiyohara ses, alg, ses->ses_hmouter, digest, 458 1.1 kiyohara 512 + dlen, 0, dlen, (char *)digest, NULL, 459 1.1 kiyohara NULL); 460 1.1 kiyohara if (crp->crp_etype != 0) 461 1.1 kiyohara break; 462 1.1 kiyohara 463 1.1 kiyohara /* Inject the authentication data */ 464 1.1 kiyohara if (buf != NULL) 465 1.1 kiyohara memcpy(buf + crd->crd_inject, digest, dlen / 8); 466 1.1 kiyohara else if (m != NULL) 467 1.1 kiyohara m_copyback(m, crd->crd_inject, dlen / 8, 468 1.1 kiyohara digest); 469 1.1 kiyohara else if (uio != NULL) 470 1.1 kiyohara memcpy(crp->crp_mac, digest, dlen / 8); 471 1.1 kiyohara } 472 1.1 kiyohara } 473 1.1 kiyohara if (crp->crp_etype != 0) 474 1.1 kiyohara break; 475 1.1 kiyohara } 476 1.1 kiyohara 477 1.1 kiyohara done: 478 1.1 kiyohara DPRINTF(("request %08x done\n", (uint32_t)crp)); 479 1.1 kiyohara crypto_done(crp); 480 1.1 kiyohara return 0; 481 1.1 kiyohara } 482 1.1 kiyohara 483 1.1 kiyohara 484 1.1 kiyohara static int 485 1.1 kiyohara mvcesa_authentication(struct mvcesa_softc *sc, struct mvcesa_session *ses, 486 1.1 kiyohara uint32_t alg, uint32_t *iv, uint32_t *digest, 487 1.1 kiyohara uint64_t bits, int skip, int len, char *buf, 488 1.1 kiyohara struct mbuf *m, struct uio *uio) 489 1.1 kiyohara { 490 1.1 kiyohara uint32_t cmd, bswp, data = 0; 491 1.1 kiyohara int dlen, off, i, s; 492 1.1 kiyohara 493 1.1 kiyohara /* 494 1.1 kiyohara * SHA/MD5 algorithms work in 512-bit chunks, equal to 16 words. 495 1.1 kiyohara */ 496 1.1 kiyohara 497 1.1 kiyohara KASSERT(!(len & (512 - 1)) || bits != 0); 498 1.1 kiyohara KASSERT(buf != NULL || m != NULL || uio != NULL); 499 1.1 kiyohara 500 1.1 kiyohara cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVCESA_SHA1MD5I_AC); 501 1.1 kiyohara if (!(cmd & MVCESA_SHA1MD5I_AC_TERMINATION)) 502 1.1 kiyohara return ERESTART; 503 1.1 kiyohara 504 1.1 kiyohara bswp = 0; 505 1.1 kiyohara if (alg == MVCESA_SHA1MD5I_AC_ALGORITHM_SHA1) { 506 1.1 kiyohara dlen = 160; 507 1.1 kiyohara bits = htobe64(bits); 508 1.1 kiyohara #if BYTE_ORDER == LITTLE_ENDIAN 509 1.1 kiyohara bswp = MVCESA_SHA1MD5I_AC_DATABYTESWAP | 510 1.1 kiyohara MVCESA_SHA1MD5I_AC_IVBYTESWAP; 511 1.1 kiyohara #endif 512 1.1 kiyohara } else { /* MVCESA_SHA1MD5I_AC_ALGORITHM_MD5 */ 513 1.1 kiyohara dlen = 128; 514 1.1 kiyohara bits = htole64(bits); 515 1.1 kiyohara #if BYTE_ORDER == BIG_ENDIAN 516 1.1 kiyohara bswp = MVCESA_SHA1MD5I_AC_DATABYTESWAP | 517 1.1 kiyohara MVCESA_SHA1MD5I_AC_IVBYTESWAP; 518 1.1 kiyohara #endif 519 1.1 kiyohara } 520 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_SHA1MD5I_AC, 521 1.1 kiyohara alg | bswp | MVCESA_SHA1MD5I_AC_MODE_USEIV); 522 1.1 kiyohara 523 1.1 kiyohara if (iv != NULL) 524 1.1 kiyohara bus_space_write_region_4(sc->sc_iot, sc->sc_ioh, 525 1.1 kiyohara MVCESA_SHA1MD5I_IVDA, iv, dlen / 4); 526 1.1 kiyohara 527 1.1 kiyohara off = i = 0; 528 1.1 kiyohara while (1 /* CONSTCOND */) { 529 1.1 kiyohara data = 0; 530 1.1 kiyohara if (buf != NULL) 531 1.1 kiyohara for (i = 0; i < 512 / 8 && off + i < len; i += s) { 532 1.2 riastrad s = uimin(sizeof(data), len - off - i); 533 1.1 kiyohara memcpy(&data, buf + skip + off + i, s); 534 1.1 kiyohara if (s == sizeof(data)) 535 1.1 kiyohara bus_space_write_4(sc->sc_iot, 536 1.1 kiyohara sc->sc_ioh, MVCESA_SHA1MD5I_DI, 537 1.1 kiyohara data); 538 1.1 kiyohara } 539 1.1 kiyohara else if (m != NULL) 540 1.1 kiyohara for (i = 0; i < 512 / 8 && off + i < len; i += s) { 541 1.2 riastrad s = uimin(sizeof(data), len - off - i); 542 1.1 kiyohara m_copydata(m, skip + off + i, s, &data); 543 1.1 kiyohara if (s == sizeof(data)) 544 1.1 kiyohara bus_space_write_4(sc->sc_iot, 545 1.1 kiyohara sc->sc_ioh, MVCESA_SHA1MD5I_DI, 546 1.1 kiyohara data); 547 1.1 kiyohara } 548 1.1 kiyohara else if (uio != NULL) 549 1.1 kiyohara for (i = 0; i < 512 / 8 && off + i < len; i += s) { 550 1.2 riastrad s = uimin(sizeof(data), len - off - i); 551 1.1 kiyohara cuio_copydata(uio, skip + off + i, s, &data); 552 1.1 kiyohara if (s == sizeof(data)) 553 1.1 kiyohara bus_space_write_4(sc->sc_iot, 554 1.1 kiyohara sc->sc_ioh, MVCESA_SHA1MD5I_DI, 555 1.1 kiyohara data); 556 1.1 kiyohara } 557 1.1 kiyohara 558 1.1 kiyohara off += i; 559 1.1 kiyohara if (i < 512 / 8) 560 1.1 kiyohara break; 561 1.1 kiyohara 562 1.1 kiyohara do { 563 1.1 kiyohara cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 564 1.1 kiyohara MVCESA_SHA1MD5I_AC); 565 1.1 kiyohara } while (!(cmd & MVCESA_SHA1MD5I_AC_TERMINATION)); 566 1.1 kiyohara 567 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_SHA1MD5I_AC, 568 1.1 kiyohara alg | bswp | MVCESA_SHA1MD5I_AC_MODE_CONTINUE); 569 1.1 kiyohara } 570 1.1 kiyohara 571 1.1 kiyohara if (i < 512 / 8) { 572 1.1 kiyohara *((char *)&data + (i % 4)) = 0x80; 573 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_SHA1MD5I_DI, 574 1.1 kiyohara data); 575 1.1 kiyohara i = (i & ~3) + 4; 576 1.1 kiyohara 577 1.1 kiyohara /* Do pad to 512 bits, if chunk size is more than 448 bits. */ 578 1.1 kiyohara if (i > 448 / 8) { 579 1.1 kiyohara for (; i < 512 / 8; i += 4) 580 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, 581 1.1 kiyohara MVCESA_SHA1MD5I_DI, 0); 582 1.1 kiyohara do { 583 1.1 kiyohara cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 584 1.1 kiyohara MVCESA_SHA1MD5I_AC); 585 1.1 kiyohara } while (!(cmd & MVCESA_SHA1MD5I_AC_TERMINATION)); 586 1.1 kiyohara i = 0; 587 1.1 kiyohara } 588 1.1 kiyohara for (; i < 448 / 8; i += 4) 589 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, 590 1.1 kiyohara MVCESA_SHA1MD5I_DI, 0); 591 1.1 kiyohara 592 1.1 kiyohara /* Set total bits */ 593 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_SHA1MD5I_BCL, 594 1.1 kiyohara bits & 0xffffffff); 595 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_SHA1MD5I_BCH, 596 1.1 kiyohara bits >> 32); 597 1.1 kiyohara do { 598 1.1 kiyohara cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 599 1.1 kiyohara MVCESA_SHA1MD5I_AC); 600 1.1 kiyohara } while (!(cmd & MVCESA_SHA1MD5I_AC_TERMINATION)); 601 1.1 kiyohara } 602 1.1 kiyohara 603 1.1 kiyohara if (digest != NULL) { 604 1.1 kiyohara /* Read digest */ 605 1.1 kiyohara bus_space_read_region_4(sc->sc_iot, sc->sc_ioh, 606 1.1 kiyohara MVCESA_SHA1MD5I_IVDA, digest, dlen / 8 / 4); 607 1.1 kiyohara #if BYTE_ORDER == LITTLE_ENDIAN 608 1.1 kiyohara if (alg == MVCESA_SHA1MD5I_AC_ALGORITHM_SHA1) 609 1.1 kiyohara for (i = 0; i < dlen / 8 / 4; i++) 610 1.1 kiyohara digest[i] = be32toh(digest[i]); 611 1.1 kiyohara #else 612 1.1 kiyohara if (alg == MVCESA_SHA1MD5I_AC_ALGORITHM_MD5) 613 1.1 kiyohara for (i = 0; i < dlen / 8 / 4; i++) 614 1.1 kiyohara digest[i] = le32toh(digest[i]); 615 1.1 kiyohara #endif 616 1.1 kiyohara } 617 1.1 kiyohara return 0; 618 1.1 kiyohara } 619 1.1 kiyohara 620 1.1 kiyohara static int 621 1.1 kiyohara mvcesa_des_encdec(struct mvcesa_softc *sc, struct mvcesa_session *ses, 622 1.1 kiyohara uint32_t alg, uint32_t mode, uint32_t dir, uint32_t *iv, 623 1.1 kiyohara int skip, int len, char *buf, struct mbuf *m, struct uio *uio) 624 1.1 kiyohara { 625 1.1 kiyohara uint64_t iblk, oblk; 626 1.1 kiyohara uint32_t cmd, bswp = 0; 627 1.1 kiyohara int i, o, s; 628 1.1 kiyohara 629 1.1 kiyohara KASSERT(buf != NULL || m != NULL || uio != NULL); 630 1.1 kiyohara 631 1.1 kiyohara cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_C); 632 1.1 kiyohara if (!(cmd & MVCESA_DESE_C_TERMINATION)) 633 1.1 kiyohara return ERESTART; 634 1.1 kiyohara 635 1.1 kiyohara #if BYTE_ORDER == LITTLE_ENDIAN 636 1.1 kiyohara bswp = MVCESA_DESE_C_DATABYTESWAP | MVCESA_DESE_C_IVBYTESWAP | 637 1.1 kiyohara MVCESA_DESE_C_OUTBYTESWAP; 638 1.1 kiyohara #endif 639 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_C, 640 1.1 kiyohara dir | alg | mode | bswp | MVCESA_DESE_C_ALLTERMINATION); 641 1.1 kiyohara 642 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_K0L, 643 1.1 kiyohara ses->ses_key[1]); 644 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_K0H, 645 1.1 kiyohara ses->ses_key[0]); 646 1.1 kiyohara if (alg == MVCESA_DESE_C_ALGORITHM_3DES) { 647 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_K1L, 648 1.1 kiyohara ses->ses_key[3]); 649 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_K1H, 650 1.1 kiyohara ses->ses_key[2]); 651 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_K2L, 652 1.1 kiyohara ses->ses_key[5]); 653 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_K2H, 654 1.1 kiyohara ses->ses_key[4]); 655 1.1 kiyohara } 656 1.1 kiyohara 657 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_IVL, iv[1]); 658 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_IVH, iv[0]); 659 1.1 kiyohara 660 1.1 kiyohara i = o = 0; 661 1.1 kiyohara while (i < len) { 662 1.2 riastrad s = uimin(sizeof(iblk), len - i); 663 1.1 kiyohara iblk = 0; 664 1.1 kiyohara 665 1.1 kiyohara if (buf != NULL) 666 1.1 kiyohara memcpy(&iblk, buf + skip + i, s); 667 1.1 kiyohara else if (m != NULL) 668 1.1 kiyohara m_copydata(m, skip + i, s, &iblk); 669 1.1 kiyohara else if (uio != NULL) 670 1.1 kiyohara cuio_copydata(uio, skip + i, s, &iblk); 671 1.1 kiyohara 672 1.1 kiyohara /* 673 1.1 kiyohara * We have the pipeline that two data enters. 674 1.1 kiyohara */ 675 1.1 kiyohara 676 1.1 kiyohara while (1 /* CONSTCOND */) { 677 1.1 kiyohara cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 678 1.1 kiyohara MVCESA_DESE_C); 679 1.1 kiyohara if (cmd & MVCESA_DESE_C_ALLTERMINATION) 680 1.1 kiyohara /* Engine is ready. Can write two data. */ 681 1.1 kiyohara break; 682 1.1 kiyohara if (cmd & MVCESA_DESE_C_READALLOW) { 683 1.1 kiyohara oblk = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 684 1.1 kiyohara MVCESA_DESE_DOH); 685 1.1 kiyohara /* XXXX: needs barrier? */ 686 1.1 kiyohara oblk |= (uint64_t)bus_space_read_4(sc->sc_iot, 687 1.1 kiyohara sc->sc_ioh, MVCESA_DESE_DOL) << 32; 688 1.1 kiyohara 689 1.1 kiyohara if (buf != NULL) 690 1.1 kiyohara memcpy(buf + skip + o, &oblk, 691 1.1 kiyohara sizeof(oblk)); 692 1.1 kiyohara else if (m != NULL) 693 1.1 kiyohara m_copydata(m, skip + o, sizeof(oblk), 694 1.1 kiyohara &oblk); 695 1.1 kiyohara else if (uio != NULL) 696 1.1 kiyohara cuio_copyback(uio, skip + o, 697 1.1 kiyohara sizeof(oblk), &oblk); 698 1.1 kiyohara o += sizeof(oblk); 699 1.1 kiyohara 700 1.1 kiyohara /* Can write one data */ 701 1.1 kiyohara break; 702 1.1 kiyohara } 703 1.1 kiyohara } 704 1.1 kiyohara 705 1.1 kiyohara /* 706 1.4 msaitoh * Encryption/Decryption calculation time is 9 cycles in DES 707 1.1 kiyohara * mode and 25 cycles in 3DES mode. 708 1.1 kiyohara */ 709 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_DBL, 710 1.1 kiyohara iblk >> 32); 711 1.1 kiyohara /* XXXX: needs barrier? */ 712 1.1 kiyohara bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVCESA_DESE_DBH, 713 1.1 kiyohara iblk & 0xffffffff); 714 1.1 kiyohara i += s; 715 1.1 kiyohara } 716 1.1 kiyohara 717 1.1 kiyohara while (1 /* CONSTCOND */) { 718 1.1 kiyohara cmd = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 719 1.1 kiyohara MVCESA_DESE_C); 720 1.1 kiyohara if (cmd & (MVCESA_DESE_C_READALLOW | 721 1.1 kiyohara MVCESA_DESE_C_ALLTERMINATION)) { 722 1.1 kiyohara oblk = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 723 1.1 kiyohara MVCESA_DESE_DOH); 724 1.1 kiyohara /* XXXX: needs barrier? */ 725 1.1 kiyohara oblk |= (uint64_t)bus_space_read_4(sc->sc_iot, 726 1.1 kiyohara sc->sc_ioh, MVCESA_DESE_DOL) << 32; 727 1.1 kiyohara 728 1.1 kiyohara if (cmd & MVCESA_DESE_C_ALLTERMINATION) { 729 1.1 kiyohara /* We can read IV from Data Out Registers. */ 730 1.1 kiyohara if (dir == MVCESA_DESE_C_DIRECTION_ENC) 731 1.1 kiyohara o -= sizeof(oblk); 732 1.1 kiyohara else 733 1.1 kiyohara break; 734 1.1 kiyohara } 735 1.1 kiyohara if (buf != NULL) 736 1.1 kiyohara memcpy(buf + skip + o, &oblk, sizeof(oblk)); 737 1.1 kiyohara else if (m != NULL) 738 1.1 kiyohara m_copydata(m, skip + o, sizeof(oblk), &oblk); 739 1.1 kiyohara else if (uio != NULL) 740 1.1 kiyohara cuio_copyback(uio, skip + o, sizeof(oblk), 741 1.1 kiyohara &oblk); 742 1.1 kiyohara o += sizeof(oblk); 743 1.1 kiyohara if (cmd & MVCESA_DESE_C_ALLTERMINATION) 744 1.1 kiyohara break; 745 1.1 kiyohara } 746 1.1 kiyohara } 747 1.1 kiyohara 748 1.1 kiyohara return 0; 749 1.1 kiyohara } 750