summaryrefslogtreecommitdiff
path: root/sys/dev/pci/aeon.c
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2000-03-10 08:45:01 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2000-03-10 08:45:01 +0000
commitc64d0d284034ee671b5098bffd9e543ef01db81a (patch)
treec5d6c66021974aa4843d6fdcb417957690e8b74c /sys/dev/pci/aeon.c
parent22dd533f383443bb637a35599d97beca6d00079f (diff)
unlock cryptography functions on Hi/fn 7751 cryptography card. Based on reverse engineering of an unlock binary provided by Invertex, for their AEON card, which uses the chip
Diffstat (limited to 'sys/dev/pci/aeon.c')
-rw-r--r--sys/dev/pci/aeon.c139
1 files changed, 117 insertions, 22 deletions
diff --git a/sys/dev/pci/aeon.c b/sys/dev/pci/aeon.c
index adc68d90ff3..1a14103f4aa 100644
--- a/sys/dev/pci/aeon.c
+++ b/sys/dev/pci/aeon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aeon.c,v 1.6 2000/01/10 02:22:50 jason Exp $ */
+/* $OpenBSD: aeon.c,v 1.7 2000/03/10 08:44:59 mickey Exp $ */
/*
* Invertex AEON driver
@@ -53,7 +53,7 @@
#include <dev/pci/aeonvar.h>
#include <dev/pci/aeonreg.h>
-#define AEON_DEBUG
+#undef AEON_DEBUG
/*
* Prototypes and count for the pci_device structure
@@ -70,7 +70,7 @@ struct cfdriver aeon_cd = {
};
void aeon_reset_board __P((struct aeon_softc *));
-int aeon_enable_crypto __P((struct aeon_softc *));
+int aeon_enable_crypto __P((struct aeon_softc *, pcireg_t));
void aeon_init_dma __P((struct aeon_softc *));
void aeon_init_pci_registers __P((struct aeon_softc *));
int aeon_checkram __P((struct aeon_softc *));
@@ -81,6 +81,7 @@ int aeon_build_command __P((const struct aeon_command * cmd,
struct aeon_command_buf_data *));
int aeon_mbuf __P((struct mbuf *, int *np, long *pp, int *lp, int maxp,
int *nicealign));
+u_int32_t aeon_next_signature __P((u_int a, u_int cnt));
/*
* Used for round robin crypto requests
@@ -155,7 +156,9 @@ aeon_attach(parent, self, aux)
return;
}
sc->sc_st1 = pa->pa_memt;
+#ifdef AEON_DEBUG
printf(" mem %x %x", sc->sc_sh0, sc->sc_sh1);
+#endif
sc->sc_dmat = pa->pa_dmat;
if (bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_dma), PAGE_SIZE, 0,
@@ -190,9 +193,8 @@ aeon_attach(parent, self, aux)
aeon_reset_board(sc);
- if (aeon_enable_crypto(sc) != 0) {
- printf("%s: crypto enabling failed\n",
- sc->sc_dv.dv_xname);
+ if (aeon_enable_crypto(sc, pa->pa_id) != 0) {
+ printf("%s: crypto enabling failed\n", sc->sc_dv.dv_xname);
return;
}
@@ -230,7 +232,7 @@ aeon_attach(parent, self, aux)
aeon_devices[aeon_num_devices] = sc;
aeon_num_devices++;
- printf(": %s\n", intrstr);
+ printf(", %s\n", intrstr);
}
/*
@@ -272,16 +274,73 @@ aeon_reset_board(sc)
AEON_DMA_CFG_NODMARESET | AEON_DMA_CFG_NEED);
}
+u_int32_t
+aeon_next_signature(a, cnt)
+ u_int a, cnt;
+{
+ int i, v;
+
+ for (i = 0; i < cnt; i++) {
+
+ /* get the parity */
+ v = a & 0x80080125;
+ v ^= v >> 16;
+ v ^= v >> 8;
+ v ^= v >> 4;
+ v ^= v >> 2;
+ v ^= v >> 1;
+
+ a = (v & 1) ^ (a << 1);
+ }
+
+ return a;
+}
+
+struct pci2id {
+ u_short pci_vendor;
+ u_short pci_prod;
+ char card_id[13];
+} pci2id[] = {
+ {
+ PCI_VENDOR_INVERTEX,
+ PCI_PRODUCT_INVERTEX_AEON,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00 }
+ }, {
+ PCI_VENDOR_HIFN,
+ PCI_PRODUCT_HIFN_7751,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00 } /* XXX incorrect */
+ },
+};
+
/*
* Checks to see if crypto is already enabled. If crypto isn't enable,
* "aeon_enable_crypto" is called to enable it. The check is important,
* as enabling crypto twice will lock the board.
*/
int
-aeon_enable_crypto(sc)
+aeon_enable_crypto(sc, pciid)
struct aeon_softc *sc;
+ pcireg_t pciid;
{
- u_int32_t encryption_level;
+ u_int32_t dmacfg, ramcfg, encl, addr, i;
+ char *offtbl = NULL;
+
+ for (i = 0; i < sizeof(pci2id)/sizeof(pci2id[0]); i++) {
+ if (pci2id[i].pci_vendor == PCI_VENDOR(pciid) &&
+ pci2id[i].pci_prod == PCI_PRODUCT(pciid)) {
+ offtbl = pci2id[i].card_id;
+ break;
+ }
+ }
+
+ if (offtbl == NULL) {
+#ifdef AEON_DEBUG
+ printf("%s: Unknown card!\n", sc->sc_dv.dv_xname);
+#endif
+ return (1);
+ }
/*
* The RAM config register's encrypt level bit needs to be set before
@@ -290,39 +349,75 @@ aeon_enable_crypto(sc)
WRITE_REG_0(sc, AEON_RAM_CONFIG,
READ_REG_0(sc, AEON_RAM_CONFIG) | (0x1 << 5));
- encryption_level = READ_REG_0(sc, AEON_CRYPTLEVEL);
+ encl = READ_REG_0(sc, AEON_CRYPTLEVEL);
/*
* Make sure we don't re-unlock. Two unlocks kills chip until the
* next reboot.
*/
- if (encryption_level == 0x1020 || encryption_level == 0x1120) {
+ if (encl == 0x1020 || encl == 0x1120) {
#ifdef AEON_DEBUG
printf("%s: Strong Crypto already enabled!\n",
sc->sc_dv.dv_xname);
#endif
+#if 0
+ /* XXX impossible, this writes garbage to these registers */
+ WRITE_REG_0(sc, AEON_RAM_CONFIG, ramcfg);
+ WRITE_REG_1(sc, AEON_DMA_CFG, dmacfg);
+#endif
return 0; /* success */
}
- /**
- **
- ** Rest of unlock procedure removed.
- **
- **
- **/
+ ramcfg = READ_REG_0(sc, AEON_RAM_CONFIG);
+ dmacfg = READ_REG_1(sc, AEON_DMA_CFG);
+
+ WRITE_REG_0(sc, AEON_RAM_CONFIG, ramcfg | 0x20);
+
+ encl = READ_REG_0(sc, AEON_CRYPTLEVEL);
+
+ if (encl != 0 && encl != 0x3020) {
+#ifdef AEON_DEBUG
+ printf("%: Unknown encryption level\n", sc->sc_dv.dv_xname);
+#endif
+ return 1;
+ }
+
+ WRITE_REG_1(sc, AEON_DMA_CFG, 0x807);
+ addr = READ_REG_1(sc, AEON_UNLOCK_SECRET1);
+ WRITE_REG_1(sc, AEON_UNLOCK_SECRET2, 0);
+
+ for (i = 0; i <= 12; i++) {
+ addr = aeon_next_signature(addr, offtbl[i] + 0x101);
+ WRITE_REG_1(sc, AEON_UNLOCK_SECRET2, addr);
+
+ DELAY(1000);
+ }
+
+ WRITE_REG_0(sc, AEON_RAM_CONFIG, ramcfg | 0x20);
+ encl = READ_REG_0(sc, AEON_CRYPTLEVEL);
+
+#ifdef AEON_DEBUG
+ if (encl != 0x1020 && encl != 0x1120)
+ printf("Encryption engine is permanently locked until next system reset.");
+ else
+ printf("Encryption engine enabled successfully!");
+#endif
+
+ WRITE_REG_0(sc, AEON_RAM_CONFIG, ramcfg);
+ WRITE_REG_1(sc, AEON_DMA_CFG, dmacfg);
- switch(encryption_level) {
+ switch(encl) {
case 0x3020:
- printf(" no encr/auth");
+ printf(": no encr/auth");
break;
case 0x1020:
- printf(" DES");
+ printf(": DES enabled");
break;
case 0x1120:
- printf(" FULL");
+ printf(": fully enabled");
break;
default:
- printf(" disabled");
+ printf(": disabled");
break;
}