[BACK]Return to glxsb.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / pci

Annotation of sys/arch/i386/pci/glxsb.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: glxsb.c,v 1.8 2007/08/07 09:48:23 markus Exp $        */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2006 Tom Cosgrove <tom@openbsd.org>
        !             5:  * Copyright (c) 2003, 2004 Theo de Raadt
        !             6:  * Copyright (c) 2003 Jason Wright
        !             7:  *
        !             8:  * Permission to use, copy, modify, and distribute this software for any
        !             9:  * purpose with or without fee is hereby granted, provided that the above
        !            10:  * copyright notice and this permission notice appear in all copies.
        !            11:  *
        !            12:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            13:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            14:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            15:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            16:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            17:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            18:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            19:  */
        !            20:
        !            21: /*
        !            22:  * Driver for the security block on the AMD Geode LX processors
        !            23:  * http://www.amd.com/files/connectivitysolutions/geode/geode_lx/33234d_lx_ds.pdf
        !            24:  */
        !            25:
        !            26: #include <sys/cdefs.h>
        !            27: #include <sys/param.h>
        !            28: #include <sys/systm.h>
        !            29: #include <sys/device.h>
        !            30: #include <sys/malloc.h>
        !            31: #include <sys/mbuf.h>
        !            32: #include <sys/types.h>
        !            33: #include <sys/timeout.h>
        !            34:
        !            35: #include <machine/bus.h>
        !            36: #include <machine/pctr.h>
        !            37:
        !            38: #include <dev/rndvar.h>
        !            39: #include <dev/pci/pcivar.h>
        !            40: #include <dev/pci/pcidevs.h>
        !            41:
        !            42: #ifdef CRYPTO
        !            43: #include <crypto/cryptodev.h>
        !            44: #include <crypto/rijndael.h>
        !            45: #include <crypto/xform.h>
        !            46: #include <crypto/cryptosoft.h>
        !            47: #endif
        !            48:
        !            49: #define SB_GLD_MSR_CAP         0x58002000      /* RO - Capabilities */
        !            50: #define SB_GLD_MSR_CONFIG      0x58002001      /* RW - Master Config */
        !            51: #define SB_GLD_MSR_SMI         0x58002002      /* RW - SMI */
        !            52: #define SB_GLD_MSR_ERROR       0x58002003      /* RW - Error */
        !            53: #define SB_GLD_MSR_PM          0x58002004      /* RW - Power Mgmt */
        !            54: #define SB_GLD_MSR_DIAG                0x58002005      /* RW - Diagnostic */
        !            55: #define SB_GLD_MSR_CTRL                0x58002006      /* RW - Security Block Cntrl */
        !            56:
        !            57:                                                /* For GLD_MSR_CTRL: */
        !            58: #define SB_GMC_DIV0            0x0000          /* AES update divisor values */
        !            59: #define SB_GMC_DIV1            0x0001
        !            60: #define SB_GMC_DIV2            0x0002
        !            61: #define SB_GMC_DIV3            0x0003
        !            62: #define SB_GMC_DIV_MASK                0x0003
        !            63: #define SB_GMC_SBI             0x0004          /* AES swap bits */
        !            64: #define SB_GMC_SBY             0x0008          /* AES swap bytes */
        !            65: #define SB_GMC_TW              0x0010          /* Time write (EEPROM) */
        !            66: #define SB_GMC_T_SEL0          0x0000          /* RNG post-proc: none */
        !            67: #define SB_GMC_T_SEL1          0x0100          /* RNG post-proc: LFSR */
        !            68: #define SB_GMC_T_SEL2          0x0200          /* RNG post-proc: whitener */
        !            69: #define SB_GMC_T_SEL3          0x0300          /* RNG LFSR+whitener */
        !            70: #define SB_GMC_T_SEL_MASK      0x0300
        !            71: #define SB_GMC_T_NE            0x0400          /* Noise (generator) Enable */
        !            72: #define SB_GMC_T_TM            0x0800          /* RNG test mode */
        !            73:                                                /*     (deterministic) */
        !            74:
        !            75: /* Security Block configuration/control registers (offsets from base) */
        !            76:
        !            77: #define SB_CTL_A               0x0000          /* RW - SB Control A */
        !            78: #define SB_CTL_B               0x0004          /* RW - SB Control B */
        !            79: #define SB_AES_INT             0x0008          /* RW - SB AES Interrupt */
        !            80: #define SB_SOURCE_A            0x0010          /* RW - Source A */
        !            81: #define SB_DEST_A              0x0014          /* RW - Destination A */
        !            82: #define SB_LENGTH_A            0x0018          /* RW - Length A */
        !            83: #define SB_SOURCE_B            0x0020          /* RW - Source B */
        !            84: #define SB_DEST_B              0x0024          /* RW - Destination B */
        !            85: #define SB_LENGTH_B            0x0028          /* RW - Length B */
        !            86: #define SB_WKEY                        0x0030          /* WO - Writable Key 0-3 */
        !            87: #define SB_WKEY_0              0x0030          /* WO - Writable Key 0 */
        !            88: #define SB_WKEY_1              0x0034          /* WO - Writable Key 1 */
        !            89: #define SB_WKEY_2              0x0038          /* WO - Writable Key 2 */
        !            90: #define SB_WKEY_3              0x003C          /* WO - Writable Key 3 */
        !            91: #define SB_CBC_IV              0x0040          /* RW - CBC IV 0-3 */
        !            92: #define SB_CBC_IV_0            0x0040          /* RW - CBC IV 0 */
        !            93: #define SB_CBC_IV_1            0x0044          /* RW - CBC IV 1 */
        !            94: #define SB_CBC_IV_2            0x0048          /* RW - CBC IV 2 */
        !            95: #define SB_CBC_IV_3            0x004C          /* RW - CBC IV 3 */
        !            96: #define SB_RANDOM_NUM          0x0050          /* RW - Random Number */
        !            97: #define SB_RANDOM_NUM_STATUS   0x0054          /* RW - Random Number Status */
        !            98: #define SB_EEPROM_COMM         0x0800          /* RW - EEPROM Command */
        !            99: #define SB_EEPROM_ADDR         0x0804          /* RW - EEPROM Address */
        !           100: #define SB_EEPROM_DATA         0x0808          /* RW - EEPROM Data */
        !           101: #define SB_EEPROM_SEC_STATE    0x080C          /* RW - EEPROM Security State */
        !           102:
        !           103:                                                /* For SB_CTL_A and _B */
        !           104: #define SB_CTL_ST              0x0001          /* Start operation (enc/dec) */
        !           105: #define SB_CTL_ENC             0x0002          /* Encrypt (0 is decrypt) */
        !           106: #define SB_CTL_DEC             0x0000          /* Decrypt */
        !           107: #define SB_CTL_WK              0x0004          /* Use writable key (we set) */
        !           108: #define SB_CTL_DC              0x0008          /* Destination coherent */
        !           109: #define SB_CTL_SC              0x0010          /* Source coherent */
        !           110: #define SB_CTL_CBC             0x0020          /* CBC (0 is ECB) */
        !           111:
        !           112:                                                /* For SB_AES_INT */
        !           113: #define SB_AI_DISABLE_AES_A    0x0001          /* Disable AES A compl int */
        !           114: #define SB_AI_ENABLE_AES_A     0x0000          /* Enable AES A compl int */
        !           115: #define SB_AI_DISABLE_AES_B    0x0002          /* Disable AES B compl int */
        !           116: #define SB_AI_ENABLE_AES_B     0x0000          /* Enable AES B compl int */
        !           117: #define SB_AI_DISABLE_EEPROM   0x0004          /* Disable EEPROM op comp int */
        !           118: #define SB_AI_ENABLE_EEPROM    0x0000          /* Enable EEPROM op compl int */
        !           119: #define SB_AI_AES_A_COMPLETE   0x0100          /* AES A operation complete */
        !           120: #define SB_AI_AES_B_COMPLETE   0x0200          /* AES B operation complete */
        !           121: #define SB_AI_EEPROM_COMPLETE  0x0400          /* EEPROM operation complete */
        !           122:
        !           123: #define SB_RNS_TRNG_VALID      0x0001          /* in SB_RANDOM_NUM_STATUS */
        !           124:
        !           125: #define SB_MEM_SIZE            0x0810          /* Size of memory block */
        !           126:
        !           127: #define SB_AES_ALIGN           0x0010          /* Source and dest buffers */
        !           128:                                                /* must be 16-byte aligned */
        !           129: #define SB_AES_BLOCK_SIZE      0x0010
        !           130:
        !           131: /*
        !           132:  * The Geode LX security block AES acceleration doesn't perform scatter-
        !           133:  * gather: it just takes source and destination addresses.  Therefore the
        !           134:  * plain- and ciphertexts need to be contiguous.  To this end, we allocate
        !           135:  * a buffer for both, and accept the overhead of copying in and out.  If
        !           136:  * the number of bytes in one operation is bigger than allowed for by the
        !           137:  * buffer (buffer is twice the size of the max length, as it has both input
        !           138:  * and output) then we have to perform multiple encryptions/decryptions.
        !           139:  */
        !           140: #define GLXSB_MAX_AES_LEN      16384
        !           141:
        !           142: #ifdef CRYPTO
        !           143: struct glxsb_dma_map {
        !           144:        bus_dmamap_t            dma_map;
        !           145:        bus_dma_segment_t       dma_seg;
        !           146:        int                     dma_nsegs;
        !           147:        int                     dma_size;
        !           148:        caddr_t                 dma_vaddr;
        !           149:        uint32_t                dma_paddr;
        !           150: };
        !           151: struct glxsb_session {
        !           152:        uint32_t        ses_key[4];
        !           153:        uint8_t         ses_iv[SB_AES_BLOCK_SIZE];
        !           154:        int             ses_klen;
        !           155:        int             ses_used;
        !           156:        struct swcr_data *ses_swd;
        !           157: };
        !           158: #endif /* CRYPTO */
        !           159:
        !           160: struct glxsb_softc {
        !           161:        struct device           sc_dev;
        !           162:        bus_space_tag_t         sc_iot;
        !           163:        bus_space_handle_t      sc_ioh;
        !           164:        struct timeout          sc_to;
        !           165:
        !           166: #ifdef CRYPTO
        !           167:        bus_dma_tag_t           sc_dmat;
        !           168:        struct glxsb_dma_map    sc_dma;
        !           169:        int32_t                 sc_cid;
        !           170:        int                     sc_nsessions;
        !           171:        struct glxsb_session    *sc_sessions;
        !           172: #endif /* CRYPTO */
        !           173: };
        !           174:
        !           175: int    glxsb_match(struct device *, void *, void *);
        !           176: void   glxsb_attach(struct device *, struct device *, void *);
        !           177: void   glxsb_rnd(void *);
        !           178:
        !           179: struct cfattach glxsb_ca = {
        !           180:        sizeof(struct glxsb_softc), glxsb_match, glxsb_attach
        !           181: };
        !           182:
        !           183: struct cfdriver glxsb_cd = {
        !           184:        NULL, "glxsb", DV_DULL
        !           185: };
        !           186:
        !           187:
        !           188: #ifdef CRYPTO
        !           189:
        !           190: #define GLXSB_SESSION(sid)             ((sid) & 0x0fffffff)
        !           191: #define        GLXSB_SID(crd,ses)              (((crd) << 28) | ((ses) & 0x0fffffff))
        !           192:
        !           193: static struct glxsb_softc *glxsb_sc;
        !           194: extern int i386_has_xcrypt;
        !           195:
        !           196: int glxsb_crypto_setup(struct glxsb_softc *);
        !           197: int glxsb_crypto_newsession(uint32_t *, struct cryptoini *);
        !           198: int glxsb_crypto_process(struct cryptop *);
        !           199: int glxsb_crypto_freesession(uint64_t);
        !           200: static __inline void glxsb_aes(struct glxsb_softc *, uint32_t, uint32_t,
        !           201:     uint32_t, void *, int, void *);
        !           202:
        !           203: int glxsb_dma_alloc(struct glxsb_softc *, int, struct glxsb_dma_map *);
        !           204: void glxsb_dma_pre_op(struct glxsb_softc *, struct glxsb_dma_map *);
        !           205: void glxsb_dma_post_op(struct glxsb_softc *, struct glxsb_dma_map *);
        !           206: void glxsb_dma_free(struct glxsb_softc *, struct glxsb_dma_map *);
        !           207:
        !           208: #endif /* CRYPTO */
        !           209:
        !           210:
        !           211: int
        !           212: glxsb_match(struct device *parent, void *match, void *aux)
        !           213: {
        !           214:        struct pci_attach_args *pa = aux;
        !           215:
        !           216:        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD &&
        !           217:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_GEODE_LX_CRYPTO)
        !           218:                return (1);
        !           219:
        !           220:        return (0);
        !           221: }
        !           222:
        !           223: void
        !           224: glxsb_attach(struct device *parent, struct device *self, void *aux)
        !           225: {
        !           226:        struct glxsb_softc *sc = (void *) self;
        !           227:        struct pci_attach_args *pa = aux;
        !           228:        bus_addr_t membase;
        !           229:        bus_size_t memsize;
        !           230:        uint64_t msr;
        !           231: #ifdef CRYPTO
        !           232:        uint32_t intr;
        !           233: #endif
        !           234:
        !           235:        msr = rdmsr(SB_GLD_MSR_CAP);
        !           236:        if ((msr & 0xFFFF00) != 0x130400) {
        !           237:                printf(": unknown ID 0x%x\n", (int) ((msr & 0xFFFF00) >> 16));
        !           238:                return;
        !           239:        }
        !           240:
        !           241:        /* printf(": revision %d", (int) (msr & 0xFF)); */
        !           242:
        !           243:        /* Map in the security block configuration/control registers */
        !           244:        if (pci_mapreg_map(pa, PCI_MAPREG_START,
        !           245:            PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_iot,
        !           246:            &sc->sc_ioh, &membase, &memsize, SB_MEM_SIZE)) {
        !           247:                printf(": can't find mem space\n");
        !           248:                return;
        !           249:        }
        !           250:
        !           251:        /*
        !           252:         * Configure the Security Block.
        !           253:         *
        !           254:         * We want to enable the noise generator (T_NE), and enable the
        !           255:         * linear feedback shift register and whitener post-processing
        !           256:         * (T_SEL = 3).  Also ensure that test mode (deterministic values)
        !           257:         * is disabled.
        !           258:         */
        !           259:        msr = rdmsr(SB_GLD_MSR_CTRL);
        !           260:        msr &= ~(SB_GMC_T_TM | SB_GMC_T_SEL_MASK);
        !           261:        msr |= SB_GMC_T_NE | SB_GMC_T_SEL3;
        !           262: #if 0
        !           263:        msr |= SB_GMC_SBI | SB_GMC_SBY;         /* for AES, if necessary */
        !           264: #endif
        !           265:        wrmsr(SB_GLD_MSR_CTRL, msr);
        !           266:
        !           267:        /* Install a periodic collector for the "true" (AMD's word) RNG */
        !           268:        timeout_set(&sc->sc_to, glxsb_rnd, sc);
        !           269:        glxsb_rnd(sc);
        !           270:        printf(": RNG");
        !           271:
        !           272: #ifdef CRYPTO
        !           273:        /* We don't have an interrupt handler, so disable completion INTs */
        !           274:        intr = SB_AI_DISABLE_AES_A | SB_AI_DISABLE_AES_B |
        !           275:            SB_AI_DISABLE_EEPROM | SB_AI_AES_A_COMPLETE |
        !           276:            SB_AI_AES_B_COMPLETE | SB_AI_EEPROM_COMPLETE;
        !           277:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, SB_AES_INT, intr);
        !           278:
        !           279:        sc->sc_dmat = pa->pa_dmat;
        !           280:
        !           281:        if (glxsb_crypto_setup(sc))
        !           282:                printf(" AES");
        !           283: #endif
        !           284:
        !           285:        printf("\n");
        !           286: }
        !           287:
        !           288: void
        !           289: glxsb_rnd(void *v)
        !           290: {
        !           291:        struct glxsb_softc *sc = v;
        !           292:        uint32_t status, value;
        !           293:        extern int hz;
        !           294:
        !           295:        status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SB_RANDOM_NUM_STATUS);
        !           296:        if (status & SB_RNS_TRNG_VALID) {
        !           297:                value = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SB_RANDOM_NUM);
        !           298:                add_true_randomness(value);
        !           299:        }
        !           300:
        !           301:        timeout_add(&sc->sc_to, (hz > 100) ? (hz / 100) : 1);
        !           302: }
        !           303:
        !           304: #ifdef CRYPTO
        !           305: int
        !           306: glxsb_crypto_setup(struct glxsb_softc *sc)
        !           307: {
        !           308:        int algs[CRYPTO_ALGORITHM_MAX + 1];
        !           309:
        !           310:        /* Allocate a contiguous DMA-able buffer to work in */
        !           311:        if (glxsb_dma_alloc(sc, GLXSB_MAX_AES_LEN * 2, &sc->sc_dma) != 0)
        !           312:                return 0;
        !           313:
        !           314:        bzero(algs, sizeof(algs));
        !           315:        algs[CRYPTO_AES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
        !           316:        algs[CRYPTO_MD5_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
        !           317:        algs[CRYPTO_SHA1_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
        !           318:        algs[CRYPTO_RIPEMD160_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
        !           319:        algs[CRYPTO_SHA2_256_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
        !           320:        algs[CRYPTO_SHA2_384_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
        !           321:        algs[CRYPTO_SHA2_512_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
        !           322:
        !           323:        sc->sc_cid = crypto_get_driverid(0);
        !           324:        if (sc->sc_cid < 0)
        !           325:                return 0;
        !           326:
        !           327:        crypto_register(sc->sc_cid, algs, glxsb_crypto_newsession,
        !           328:            glxsb_crypto_freesession, glxsb_crypto_process);
        !           329:
        !           330:        sc->sc_nsessions = 0;
        !           331:
        !           332:        glxsb_sc = sc;
        !           333:
        !           334:        return 1;
        !           335: }
        !           336:
        !           337: int
        !           338: glxsb_crypto_newsession(uint32_t *sidp, struct cryptoini *cri)
        !           339: {
        !           340:        struct glxsb_softc *sc = glxsb_sc;
        !           341:        struct glxsb_session *ses = NULL;
        !           342:        struct auth_hash        *axf;
        !           343:        struct cryptoini        *c;
        !           344:        struct swcr_data        *swd;
        !           345:        int sesn, i;
        !           346:
        !           347:        if (sc == NULL || sidp == NULL || cri == NULL)
        !           348:                return (EINVAL);
        !           349:
        !           350:        for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
        !           351:                if (sc->sc_sessions[sesn].ses_used == 0) {
        !           352:                        ses = &sc->sc_sessions[sesn];
        !           353:                        break;
        !           354:                }
        !           355:        }
        !           356:
        !           357:        if (ses == NULL) {
        !           358:                sesn = sc->sc_nsessions;
        !           359:                ses = malloc((sesn + 1) * sizeof(*ses), M_DEVBUF, M_NOWAIT);
        !           360:                if (ses == NULL)
        !           361:                        return (ENOMEM);
        !           362:                if (sesn != 0) {
        !           363:                        bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
        !           364:                        bzero(sc->sc_sessions, sesn * sizeof(*ses));
        !           365:                        free(sc->sc_sessions, M_DEVBUF);
        !           366:                }
        !           367:                sc->sc_sessions = ses;
        !           368:                ses = &sc->sc_sessions[sesn];
        !           369:                sc->sc_nsessions++;
        !           370:        }
        !           371:
        !           372:        bzero(ses, sizeof(*ses));
        !           373:        ses->ses_used = 1;
        !           374:
        !           375:        for (c = cri; c != NULL; c = c->cri_next) {
        !           376:                switch (c->cri_alg) {
        !           377:                case CRYPTO_AES_CBC:
        !           378:                        if (c->cri_klen != 128) {
        !           379:                                glxsb_crypto_freesession(sesn);
        !           380:                                return (EINVAL);
        !           381:                        }
        !           382:
        !           383:                        get_random_bytes(ses->ses_iv, sizeof(ses->ses_iv));
        !           384:                        ses->ses_klen = c->cri_klen;
        !           385:
        !           386:                        /* Copy the key (Geode LX wants the primary key only) */
        !           387:                        bcopy(c->cri_key, ses->ses_key, sizeof(ses->ses_key));
        !           388:                        break;
        !           389:
        !           390:                case CRYPTO_MD5_HMAC:
        !           391:                        axf = &auth_hash_hmac_md5_96;
        !           392:                        goto authcommon;
        !           393:                case CRYPTO_SHA1_HMAC:
        !           394:                        axf = &auth_hash_hmac_sha1_96;
        !           395:                        goto authcommon;
        !           396:                case CRYPTO_RIPEMD160_HMAC:
        !           397:                        axf = &auth_hash_hmac_ripemd_160_96;
        !           398:                        goto authcommon;
        !           399:                case CRYPTO_SHA2_256_HMAC:
        !           400:                        axf = &auth_hash_hmac_sha2_256_96;
        !           401:                        goto authcommon;
        !           402:                case CRYPTO_SHA2_384_HMAC:
        !           403:                        axf = &auth_hash_hmac_sha2_384_96;
        !           404:                        goto authcommon;
        !           405:                case CRYPTO_SHA2_512_HMAC:
        !           406:                        axf = &auth_hash_hmac_sha2_512_96;
        !           407:                authcommon:
        !           408:                        MALLOC(swd, struct swcr_data *,
        !           409:                            sizeof(struct swcr_data), M_CRYPTO_DATA,
        !           410:                            M_NOWAIT);
        !           411:                        if (swd == NULL) {
        !           412:                                glxsb_crypto_freesession(sesn);
        !           413:                                return (ENOMEM);
        !           414:                        }
        !           415:                        bzero(swd, sizeof(struct swcr_data));
        !           416:                        ses->ses_swd = swd;
        !           417:
        !           418:                        swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
        !           419:                            M_NOWAIT);
        !           420:                        if (swd->sw_ictx == NULL) {
        !           421:                                glxsb_crypto_freesession(sesn);
        !           422:                                return (ENOMEM);
        !           423:                        }
        !           424:
        !           425:                        swd->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
        !           426:                            M_NOWAIT);
        !           427:                        if (swd->sw_octx == NULL) {
        !           428:                                glxsb_crypto_freesession(sesn);
        !           429:                                return (ENOMEM);
        !           430:                        }
        !           431:
        !           432:                        for (i = 0; i < c->cri_klen / 8; i++)
        !           433:                                c->cri_key[i] ^= HMAC_IPAD_VAL;
        !           434:
        !           435:                        axf->Init(swd->sw_ictx);
        !           436:                        axf->Update(swd->sw_ictx, c->cri_key, c->cri_klen / 8);
        !           437:                        axf->Update(swd->sw_ictx, hmac_ipad_buffer,
        !           438:                            HMAC_BLOCK_LEN - (c->cri_klen / 8));
        !           439:
        !           440:                        for (i = 0; i < c->cri_klen / 8; i++)
        !           441:                                c->cri_key[i] ^= (HMAC_IPAD_VAL ^
        !           442:                                    HMAC_OPAD_VAL);
        !           443:
        !           444:                        axf->Init(swd->sw_octx);
        !           445:                        axf->Update(swd->sw_octx, c->cri_key, c->cri_klen / 8);
        !           446:                        axf->Update(swd->sw_octx, hmac_opad_buffer,
        !           447:                            HMAC_BLOCK_LEN - (c->cri_klen / 8));
        !           448:
        !           449:                        for (i = 0; i < c->cri_klen / 8; i++)
        !           450:                                c->cri_key[i] ^= HMAC_OPAD_VAL;
        !           451:
        !           452:                        swd->sw_axf = axf;
        !           453:                        swd->sw_alg = c->cri_alg;
        !           454:
        !           455:                        break;
        !           456:                default:
        !           457:                        glxsb_crypto_freesession(sesn);
        !           458:                        return (EINVAL);
        !           459:                }
        !           460:        }
        !           461:
        !           462:        *sidp = GLXSB_SID(0, sesn);
        !           463:        return (0);
        !           464: }
        !           465:
        !           466: int
        !           467: glxsb_crypto_freesession(uint64_t tid)
        !           468: {
        !           469:        struct glxsb_softc *sc = glxsb_sc;
        !           470:        struct swcr_data *swd;
        !           471:        struct auth_hash *axf;
        !           472:        int sesn;
        !           473:        uint32_t sid = ((uint32_t)tid) & 0xffffffff;
        !           474:
        !           475:        if (sc == NULL)
        !           476:                return (EINVAL);
        !           477:        sesn = GLXSB_SESSION(sid);
        !           478:        if (sesn >= sc->sc_nsessions)
        !           479:                return (EINVAL);
        !           480:        if (sc->sc_sessions[sesn].ses_swd) {
        !           481:                swd = sc->sc_sessions[sesn].ses_swd;
        !           482:                axf = swd->sw_axf;
        !           483:
        !           484:                if (swd->sw_ictx) {
        !           485:                        bzero(swd->sw_ictx, axf->ctxsize);
        !           486:                        free(swd->sw_ictx, M_CRYPTO_DATA);
        !           487:                }
        !           488:                if (swd->sw_octx) {
        !           489:                        bzero(swd->sw_octx, axf->ctxsize);
        !           490:                        free(swd->sw_octx, M_CRYPTO_DATA);
        !           491:                }
        !           492:                FREE(swd, M_CRYPTO_DATA);
        !           493:        }
        !           494:        bzero(&sc->sc_sessions[sesn], sizeof(sc->sc_sessions[sesn]));
        !           495:        return (0);
        !           496: }
        !           497:
        !           498: /*
        !           499:  * Must be called at splnet() or higher
        !           500:  */
        !           501: static __inline void
        !           502: glxsb_aes(struct glxsb_softc *sc, uint32_t control, uint32_t psrc,
        !           503:     uint32_t pdst, void *key, int len, void *iv)
        !           504: {
        !           505:        uint32_t status;
        !           506:        int i;
        !           507:
        !           508:        if (len & 0xF) {
        !           509:                printf("%s: len must be a multiple of 16 (not %d)\n",
        !           510:                    sc->sc_dev.dv_xname, len);
        !           511:                return;
        !           512:        }
        !           513:
        !           514:        /* Set the source */
        !           515:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, SB_SOURCE_A, psrc);
        !           516:
        !           517:        /* Set the destination address */
        !           518:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, SB_DEST_A, pdst);
        !           519:
        !           520:        /* Set the data length */
        !           521:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, SB_LENGTH_A, len);
        !           522:
        !           523:        /* Set the IV */
        !           524:        if (iv != NULL) {
        !           525:                bus_space_write_region_4(sc->sc_iot, sc->sc_ioh,
        !           526:                    SB_CBC_IV, iv, 4);
        !           527:                control |= SB_CTL_CBC;
        !           528:        }
        !           529:
        !           530:        /* Set the key */
        !           531:        bus_space_write_region_4(sc->sc_iot, sc->sc_ioh, SB_WKEY, key, 4);
        !           532:
        !           533:        /* Ask the security block to do it */
        !           534:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, SB_CTL_A,
        !           535:            control | SB_CTL_WK | SB_CTL_DC | SB_CTL_SC | SB_CTL_ST);
        !           536:
        !           537:        /*
        !           538:         * Now wait until it is done.
        !           539:         *
        !           540:         * We do a busy wait.  Obviously the number of iterations of
        !           541:         * the loop required to perform the AES operation depends upon
        !           542:         * the number of bytes to process.
        !           543:         *
        !           544:         * On a 500 MHz Geode LX we see
        !           545:         *
        !           546:         *      length (bytes)  typical max iterations
        !           547:         *          16             12
        !           548:         *          64             22
        !           549:         *         256             59
        !           550:         *        1024            212
        !           551:         *        8192          1,537
        !           552:         *
        !           553:         * Since we have a maximum size of operation defined in
        !           554:         * GLXSB_MAX_AES_LEN, we use this constant to decide how long
        !           555:         * to wait.  Allow an order of magnitude longer than it should
        !           556:         * really take, just in case.
        !           557:         */
        !           558:        for (i = 0; i < GLXSB_MAX_AES_LEN * 10; i++) {
        !           559:                status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SB_CTL_A);
        !           560:
        !           561:                if ((status & SB_CTL_ST) == 0)          /* Done */
        !           562:                        return;
        !           563:        }
        !           564:
        !           565:        printf("%s: operation failed to complete\n", sc->sc_dev.dv_xname);
        !           566: }
        !           567:
        !           568: static int
        !           569: glxsb_crypto_swauth(struct cryptop *crp, struct cryptodesc *crd,
        !           570:     struct swcr_data *sw, caddr_t buf)
        !           571: {
        !           572:        int     type;
        !           573:
        !           574:        if (crp->crp_flags & CRYPTO_F_IMBUF)
        !           575:                type = CRYPTO_BUF_MBUF;
        !           576:        else
        !           577:                type = CRYPTO_BUF_IOV;
        !           578:
        !           579:        return (swcr_authcompute(crp, crd, sw, buf, type));
        !           580: }
        !           581:
        !           582: static int
        !           583: glxsb_crypto_encdec(struct cryptop *crp, struct cryptodesc *crd,
        !           584:     struct glxsb_session *ses, struct glxsb_softc *sc, caddr_t buf)
        !           585: {
        !           586:        char *op_src, *op_dst;
        !           587:        uint32_t op_psrc, op_pdst;
        !           588:        uint8_t op_iv[SB_AES_BLOCK_SIZE], *piv;
        !           589:        int err = 0;
        !           590:        int len, tlen, xlen;
        !           591:        int offset;
        !           592:        uint32_t control;
        !           593:
        !           594:        if (crd == NULL || (crd->crd_len % SB_AES_BLOCK_SIZE) != 0) {
        !           595:                err = EINVAL;
        !           596:                goto out;
        !           597:        }
        !           598:
        !           599:        /* How much of our buffer will we need to use? */
        !           600:        xlen = crd->crd_len > GLXSB_MAX_AES_LEN ?
        !           601:            GLXSB_MAX_AES_LEN : crd->crd_len;
        !           602:
        !           603:        /*
        !           604:         * XXX Check if we can have input == output on Geode LX.
        !           605:         * XXX In the meantime, use two separate (adjacent) buffers.
        !           606:         */
        !           607:        op_src = sc->sc_dma.dma_vaddr;
        !           608:        op_dst = sc->sc_dma.dma_vaddr + xlen;
        !           609:
        !           610:        op_psrc = sc->sc_dma.dma_paddr;
        !           611:        op_pdst = sc->sc_dma.dma_paddr + xlen;
        !           612:
        !           613:        if (crd->crd_flags & CRD_F_ENCRYPT) {
        !           614:                control = SB_CTL_ENC;
        !           615:                if (crd->crd_flags & CRD_F_IV_EXPLICIT)
        !           616:                        bcopy(crd->crd_iv, op_iv, sizeof(op_iv));
        !           617:                else
        !           618:                        bcopy(ses->ses_iv, op_iv, sizeof(op_iv));
        !           619:
        !           620:                if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
        !           621:                        if (crp->crp_flags & CRYPTO_F_IMBUF)
        !           622:                                m_copyback((struct mbuf *)crp->crp_buf,
        !           623:                                    crd->crd_inject, sizeof(op_iv), op_iv);
        !           624:                        else if (crp->crp_flags & CRYPTO_F_IOV)
        !           625:                                cuio_copyback((struct uio *)crp->crp_buf,
        !           626:                                    crd->crd_inject, sizeof(op_iv), op_iv);
        !           627:                        else
        !           628:                                bcopy(op_iv,
        !           629:                                    crp->crp_buf + crd->crd_inject, sizeof(op_iv));
        !           630:                }
        !           631:        } else {
        !           632:                control = SB_CTL_DEC;
        !           633:                if (crd->crd_flags & CRD_F_IV_EXPLICIT)
        !           634:                        bcopy(crd->crd_iv, op_iv, sizeof(op_iv));
        !           635:                else {
        !           636:                        if (crp->crp_flags & CRYPTO_F_IMBUF)
        !           637:                                m_copydata((struct mbuf *)crp->crp_buf,
        !           638:                                    crd->crd_inject, sizeof(op_iv), op_iv);
        !           639:                        else if (crp->crp_flags & CRYPTO_F_IOV)
        !           640:                                cuio_copydata((struct uio *)crp->crp_buf,
        !           641:                                    crd->crd_inject, sizeof(op_iv), op_iv);
        !           642:                        else
        !           643:                                bcopy(crp->crp_buf + crd->crd_inject,
        !           644:                                    op_iv, sizeof(op_iv));
        !           645:                }
        !           646:        }
        !           647:
        !           648:        offset = 0;
        !           649:        tlen = crd->crd_len;
        !           650:        piv = op_iv;
        !           651:
        !           652:        /* Process the data in GLXSB_MAX_AES_LEN chunks */
        !           653:        while (tlen > 0) {
        !           654:                len = (tlen > GLXSB_MAX_AES_LEN) ? GLXSB_MAX_AES_LEN : tlen;
        !           655:
        !           656:                if (crp->crp_flags & CRYPTO_F_IMBUF)
        !           657:                        m_copydata((struct mbuf *)crp->crp_buf,
        !           658:                            crd->crd_skip + offset, len, op_src);
        !           659:                else if (crp->crp_flags & CRYPTO_F_IOV)
        !           660:                        cuio_copydata((struct uio *)crp->crp_buf,
        !           661:                            crd->crd_skip + offset, len, op_src);
        !           662:                else
        !           663:                        bcopy(crp->crp_buf + crd->crd_skip + offset, op_src,
        !           664:                            len);
        !           665:
        !           666:                glxsb_dma_pre_op(sc, &sc->sc_dma);
        !           667:
        !           668:                glxsb_aes(sc, control, op_psrc, op_pdst, ses->ses_key,
        !           669:                    len, op_iv);
        !           670:
        !           671:                glxsb_dma_post_op(sc, &sc->sc_dma);
        !           672:
        !           673:                if (crp->crp_flags & CRYPTO_F_IMBUF)
        !           674:                        m_copyback((struct mbuf *)crp->crp_buf,
        !           675:                            crd->crd_skip + offset, len, op_dst);
        !           676:                else if (crp->crp_flags & CRYPTO_F_IOV)
        !           677:                        cuio_copyback((struct uio *)crp->crp_buf,
        !           678:                            crd->crd_skip + offset, len, op_dst);
        !           679:                else
        !           680:                        bcopy(op_dst, crp->crp_buf + crd->crd_skip + offset,
        !           681:                            len);
        !           682:
        !           683:                offset += len;
        !           684:                tlen -= len;
        !           685:
        !           686:                if (tlen <= 0) {        /* Ideally, just == 0 */
        !           687:                        /* Finished - put the IV in session IV */
        !           688:                        piv = ses->ses_iv;
        !           689:                }
        !           690:
        !           691:                /*
        !           692:                 * Copy out last block for use as next iteration/session IV.
        !           693:                 *
        !           694:                 * piv is set to op_iv[] before the loop starts, but is
        !           695:                 * set to ses->ses_iv if we're going to exit the loop this
        !           696:                 * time.
        !           697:                 */
        !           698:                if (crd->crd_flags & CRD_F_ENCRYPT) {
        !           699:                        bcopy(op_dst + len - sizeof(op_iv), piv, sizeof(op_iv));
        !           700:                } else {
        !           701:                        /* Decryption, only need this if another iteration */
        !           702:                        if (tlen > 0) {
        !           703:                                bcopy(op_src + len - sizeof(op_iv), piv,
        !           704:                                    sizeof(op_iv));
        !           705:                        }
        !           706:                }
        !           707:        }
        !           708:
        !           709:        /* All AES processing has now been done. */
        !           710:        bzero(sc->sc_dma.dma_vaddr, xlen * 2);
        !           711:
        !           712: out:
        !           713:        return (err);
        !           714: }
        !           715:
        !           716: int
        !           717: glxsb_crypto_process(struct cryptop *crp)
        !           718: {
        !           719:        struct glxsb_softc *sc = glxsb_sc;
        !           720:        struct glxsb_session *ses;
        !           721:        struct cryptodesc *crd;
        !           722:        int sesn,err = 0;
        !           723:        int s;
        !           724:
        !           725:        s = splnet();
        !           726:
        !           727:        if (crp == NULL || crp->crp_callback == NULL) {
        !           728:                err = EINVAL;
        !           729:                goto out;
        !           730:        }
        !           731:        crd = crp->crp_desc;
        !           732:        if (crd == NULL) {
        !           733:                err = EINVAL;
        !           734:                goto out;
        !           735:        }
        !           736:
        !           737:        sesn = GLXSB_SESSION(crp->crp_sid);
        !           738:        if (sesn >= sc->sc_nsessions) {
        !           739:                err = EINVAL;
        !           740:                goto out;
        !           741:        }
        !           742:        ses = &sc->sc_sessions[sesn];
        !           743:
        !           744:        for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
        !           745:                switch (crd->crd_alg) {
        !           746:                case CRYPTO_AES_CBC:
        !           747:                        if ((err = glxsb_crypto_encdec(crp, crd, ses, sc,
        !           748:                            crp->crp_buf)) != 0)
        !           749:                                goto out;
        !           750:                        break;
        !           751:
        !           752:                case CRYPTO_MD5_HMAC:
        !           753:                case CRYPTO_SHA1_HMAC:
        !           754:                case CRYPTO_RIPEMD160_HMAC:
        !           755:                case CRYPTO_SHA2_256_HMAC:
        !           756:                case CRYPTO_SHA2_384_HMAC:
        !           757:                case CRYPTO_SHA2_512_HMAC:
        !           758:                        if ((err = glxsb_crypto_swauth(crp, crd, ses->ses_swd,
        !           759:                            crp->crp_buf)) != 0)
        !           760:                                goto out;
        !           761:                        break;
        !           762:
        !           763:                default:
        !           764:                        err = EINVAL;
        !           765:                        goto out;
        !           766:                }
        !           767:        }
        !           768:
        !           769: out:
        !           770:        crp->crp_etype = err;
        !           771:        crypto_done(crp);
        !           772:        splx(s);
        !           773:        return (err);
        !           774: }
        !           775:
        !           776: int
        !           777: glxsb_dma_alloc(struct glxsb_softc *sc, int size, struct glxsb_dma_map *dma)
        !           778: {
        !           779:        int rc;
        !           780:
        !           781:        dma->dma_nsegs = 1;
        !           782:        dma->dma_size = size;
        !           783:
        !           784:        rc = bus_dmamap_create(sc->sc_dmat, size, dma->dma_nsegs, size,
        !           785:            0, BUS_DMA_NOWAIT, &dma->dma_map);
        !           786:        if (rc != 0) {
        !           787:                printf("%s: couldn't create DMA map for %d bytes (%d)\n",
        !           788:                    sc->sc_dev.dv_xname, size, rc);
        !           789:
        !           790:                goto fail0;
        !           791:        }
        !           792:
        !           793:        rc = bus_dmamem_alloc(sc->sc_dmat, size, SB_AES_ALIGN, 0,
        !           794:            &dma->dma_seg, dma->dma_nsegs, &dma->dma_nsegs, BUS_DMA_NOWAIT);
        !           795:        if (rc != 0) {
        !           796:                printf("%s: couldn't allocate DMA memory of %d bytes (%d)\n",
        !           797:                    sc->sc_dev.dv_xname, size, rc);
        !           798:
        !           799:                goto fail1;
        !           800:        }
        !           801:
        !           802:        rc = bus_dmamem_map(sc->sc_dmat, &dma->dma_seg, 1, size,
        !           803:            &dma->dma_vaddr, BUS_DMA_NOWAIT);
        !           804:        if (rc != 0) {
        !           805:                printf("%s: couldn't map DMA memory for %d bytes (%d)\n",
        !           806:                    sc->sc_dev.dv_xname, size, rc);
        !           807:
        !           808:                goto fail2;
        !           809:        }
        !           810:
        !           811:        rc = bus_dmamap_load(sc->sc_dmat, dma->dma_map, dma->dma_vaddr,
        !           812:            size, NULL, BUS_DMA_NOWAIT);
        !           813:        if (rc != 0) {
        !           814:                printf("%s: couldn't load DMA memory for %d bytes (%d)\n",
        !           815:                    sc->sc_dev.dv_xname, size, rc);
        !           816:
        !           817:                goto fail3;
        !           818:        }
        !           819:
        !           820:        dma->dma_paddr = dma->dma_map->dm_segs[0].ds_addr;
        !           821:
        !           822:        return 0;
        !           823:
        !           824: fail3:
        !           825:        bus_dmamem_unmap(sc->sc_dmat, dma->dma_vaddr, size);
        !           826: fail2:
        !           827:        bus_dmamem_free(sc->sc_dmat, &dma->dma_seg, dma->dma_nsegs);
        !           828: fail1:
        !           829:        bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
        !           830: fail0:
        !           831:        return rc;
        !           832: }
        !           833:
        !           834: void
        !           835: glxsb_dma_pre_op(struct glxsb_softc *sc, struct glxsb_dma_map *dma)
        !           836: {
        !           837:        bus_dmamap_sync(sc->sc_dmat, dma->dma_map, 0, dma->dma_size,
        !           838:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        !           839: }
        !           840:
        !           841: void
        !           842: glxsb_dma_post_op(struct glxsb_softc *sc, struct glxsb_dma_map *dma)
        !           843: {
        !           844:        bus_dmamap_sync(sc->sc_dmat, dma->dma_map, 0, dma->dma_size,
        !           845:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        !           846: }
        !           847:
        !           848: void
        !           849: glxsb_dma_free(struct glxsb_softc *sc, struct glxsb_dma_map *dma)
        !           850: {
        !           851:        bus_dmamap_unload(sc->sc_dmat, dma->dma_map);
        !           852:        bus_dmamem_unmap(sc->sc_dmat, dma->dma_vaddr, dma->dma_size);
        !           853:        bus_dmamem_free(sc->sc_dmat, &dma->dma_seg, dma->dma_nsegs);
        !           854:        bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
        !           855: }
        !           856:
        !           857: #endif /* CRYPTO */

CVSweb