Home | History | Annotate | Line # | Download | only in marvell
      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