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