Annotation of sys/arch/i386/pci/glxsb.c, Revision 1.1.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