static int pbkdf2(uint8_t *passphrase, size_t passphraselen, uint8_t *salt, size_t saltlen, uint64_t iterations, uint8_t *output, size_t outputlen) { int ret; uint64_t iter; uint32_t blockptr, i; uint16_t hmac_key_len; uint8_t *hmac_key; uint8_t block[SHA1_DIGEST_LEN * 2]; uint8_t *hmacresult = block + SHA1_DIGEST_LEN; crypto_mechanism_t mech; crypto_key_t key; crypto_data_t in_data, out_data; crypto_ctx_template_t tmpl = NULL; /* initialize output */ memset(output, 0, outputlen); /* initialize icp for use */ thread_init(); icp_init(); /* HMAC key size is max(sizeof(uint32_t) + salt len, sha 256 len) */ if (saltlen > SHA1_DIGEST_LEN) { hmac_key_len = saltlen + sizeof (uint32_t); } else { hmac_key_len = SHA1_DIGEST_LEN; } hmac_key = calloc(hmac_key_len, 1); if (!hmac_key) { ret = ENOMEM; goto error; } /* initialize sha 256 hmac mechanism */ mech.cm_type = crypto_mech2id(SUN_CKM_SHA1_HMAC); mech.cm_param = NULL; mech.cm_param_len = 0; /* initialize passphrase as a crypto key */ key.ck_format = CRYPTO_KEY_RAW; key.ck_length = CRYPTO_BYTES2BITS(passphraselen); key.ck_data = passphrase; /* * initialize crypto data for the input data. length will change * after the first iteration, so we will initialize it in the loop. */ in_data.cd_format = CRYPTO_DATA_RAW; in_data.cd_offset = 0; in_data.cd_raw.iov_base = (char *)hmac_key; /* initialize crypto data for the output data */ out_data.cd_format = CRYPTO_DATA_RAW; out_data.cd_offset = 0; out_data.cd_length = SHA1_DIGEST_LEN; out_data.cd_raw.iov_base = (char *)hmacresult; out_data.cd_raw.iov_len = out_data.cd_length; /* initialize the context template */ ret = crypto_create_ctx_template(&mech, &key, &tmpl, KM_SLEEP); if (ret != CRYPTO_SUCCESS) { ret = EIO; goto error; } /* main loop */ for (blockptr = 0; blockptr < outputlen; blockptr += SHA1_DIGEST_LEN) { /* * for the first iteration, the HMAC key is the user-provided * salt concatenated with the block index (1-indexed) */ i = htobe32(1 + (blockptr / SHA1_DIGEST_LEN)); memmove(hmac_key, salt, saltlen); memmove(hmac_key + saltlen, (uint8_t *)(&i), sizeof (uint32_t)); /* block initializes to zeroes (no XOR) */ memset(block, 0, SHA1_DIGEST_LEN); for (iter = 0; iter < iterations; iter++) { if (iter > 0) { in_data.cd_length = SHA1_DIGEST_LEN; in_data.cd_raw.iov_len = in_data.cd_length; } else { in_data.cd_length = saltlen + sizeof (uint32_t); in_data.cd_raw.iov_len = in_data.cd_length; } ret = crypto_mac(&mech, &in_data, &key, tmpl, &out_data, NULL); if (ret != CRYPTO_SUCCESS) { ret = EIO; goto error; } /* HMAC key now becomes the output of this iteration */ memmove(hmac_key, hmacresult, SHA1_DIGEST_LEN); /* XOR this iteration's result with the current block */ for (i = 0; i < SHA1_DIGEST_LEN; i++) { block[i] ^= hmacresult[i]; } } /* * compute length of this block, make sure we don't write * beyond the end of the output, truncating if necessary */ if (blockptr + SHA1_DIGEST_LEN > outputlen) { memmove(output + blockptr, block, outputlen - blockptr); } else { memmove(output + blockptr, block, SHA1_DIGEST_LEN); } } crypto_destroy_ctx_template(tmpl); free(hmac_key); icp_fini(); thread_fini(); return (0); error: crypto_destroy_ctx_template(tmpl); if (hmac_key != NULL) free(hmac_key); icp_fini(); thread_fini(); return (ret); }
void icp_pci_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa; struct icp_softc *icp; bus_space_tag_t dpmemt, iomemt, iot; bus_space_handle_t dpmemh, iomemh, ioh; bus_addr_t dpmembase, iomembase, iobase; bus_size_t dpmemsize, iomemsize, iosize; u_int32_t status; #define DPMEM_MAPPED 1 #define IOMEM_MAPPED 2 #define IO_MAPPED 4 #define INTR_ESTABLISHED 8 int retries; u_int8_t protocol; pci_intr_handle_t ih; const char *intrstr; char intrbuf[PCI_INTRSTR_LEN]; pa = aux; status = 0; icp = device_private(self); icp->icp_dv = self; icp->icp_class = icp_pci_find_class(pa); aprint_naive(": RAID controller\n"); aprint_normal(": "); if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VORTEX && PCI_PRODUCT(pa->pa_id) >= ICP_PCI_PRODUCT_FC) icp->icp_class |= ICP_FC; if (pci_mapreg_map(pa, ICP_CLASS(icp) == ICP_PCINEW ? ICP_PCINEW_DPMEM : ICP_PCI_DPMEM, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &dpmemt, &dpmemh, &dpmembase, &dpmemsize)) { if (pci_mapreg_map(pa, ICP_CLASS(icp) == ICP_PCINEW ? ICP_PCINEW_DPMEM : ICP_PCI_DPMEM, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT_1M, 0, &dpmemt, &dpmemh, &dpmembase, &dpmemsize)) { aprint_error("cannot map DPMEM\n"); goto bail_out; } } status |= DPMEM_MAPPED; icp->icp_dpmemt = dpmemt; icp->icp_dpmemh = dpmemh; icp->icp_dpmembase = dpmembase; icp->icp_dmat = pa->pa_dmat; /* * The ICP_PCINEW series also has two other regions to map. */ if (ICP_CLASS(icp) == ICP_PCINEW) { if (pci_mapreg_map(pa, ICP_PCINEW_IOMEM, PCI_MAPREG_TYPE_MEM, 0, &iomemt, &iomemh, &iomembase, &iomemsize)) { aprint_error("cannot map memory mapped I/O ports\n"); goto bail_out; } status |= IOMEM_MAPPED; if (pci_mapreg_map(pa, ICP_PCINEW_IO, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, &iobase, &iosize)) { aprint_error("cannot map I/O ports\n"); goto bail_out; } status |= IO_MAPPED; icp->icp_iot = iot; icp->icp_ioh = ioh; icp->icp_iobase = iobase; } switch (ICP_CLASS(icp)) { case ICP_PCI: bus_space_set_region_4(dpmemt, dpmemh, 0, 0, ICP_DPR_IF_SZ >> 2); if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) { aprint_error("cannot write to DPMEM\n"); goto bail_out; } #if 0 /* disable board interrupts, deinit services */ icph_writeb(0xff, &dp6_ptr->io.irqdel); icph_writeb(0x00, &dp6_ptr->io.irqen); icph_writeb(0x00, &dp6_ptr->u.ic.S_Status); icph_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index); icph_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]); icph_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx); icph_writeb(0, &dp6_ptr->io.event); retries = INIT_RETRIES; icph_delay(20); while (icph_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("initialization error (DEINIT failed)\n"); icph_munmap(ha->brd); return 0; } icph_delay(1); } prot_ver = (unchar)icph_readl(&dp6_ptr->u.ic.S_Info[0]); icph_writeb(0, &dp6_ptr->u.ic.S_Status); icph_writeb(0xff, &dp6_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("illegal protocol version\n"); icph_munmap(ha->brd); return 0; } ha->type = ICP_PCI; ha->ic_all_size = sizeof(dp6_ptr->u); /* special command to controller BIOS */ icph_writel(0x00, &dp6_ptr->u.ic.S_Info[0]); icph_writel(0x00, &dp6_ptr->u.ic.S_Info[1]); icph_writel(0x01, &dp6_ptr->u.ic.S_Info[2]); icph_writel(0x00, &dp6_ptr->u.ic.S_Info[3]); icph_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); icph_writeb(0, &dp6_ptr->io.event); retries = INIT_RETRIES; icph_delay(20); while (icph_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("initialization error\n"); icph_munmap(ha->brd); return 0; } icph_delay(1); } icph_writeb(0, &dp6_ptr->u.ic.S_Status); icph_writeb(0xff, &dp6_ptr->io.irqdel); #endif icp->icp_ic_all_size = ICP_DPRAM_SZ; icp->icp_copy_cmd = icp_pci_copy_cmd; icp->icp_get_status = icp_pci_get_status; icp->icp_intr = icp_pci_intr; icp->icp_release_event = icp_pci_release_event; icp->icp_set_sema0 = icp_pci_set_sema0; icp->icp_test_busy = icp_pci_test_busy; break; case ICP_PCINEW: bus_space_set_region_4(dpmemt, dpmemh, 0, 0, ICP_DPR_IF_SZ >> 2); if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) { aprint_error("cannot write to DPMEM\n"); goto bail_out; } #if 0 /* disable board interrupts, deinit services */ outb(0x00,PTR2USHORT(&ha->plx->control1)); outb(0xff,PTR2USHORT(&ha->plx->edoor_reg)); icph_writeb(0x00, &dp6c_ptr->u.ic.S_Status); icph_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); icph_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); icph_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; icph_delay(20); while (icph_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("initialization error (DEINIT failed)\n"); icph_munmap(ha->brd); return 0; } icph_delay(1); } prot_ver = (unchar)icph_readl(&dp6c_ptr->u.ic.S_Info[0]); icph_writeb(0, &dp6c_ptr->u.ic.Status); if (prot_ver != PROTOCOL_VERSION) { printk("illegal protocol version\n"); icph_munmap(ha->brd); return 0; } ha->type = ICP_PCINEW; ha->ic_all_size = sizeof(dp6c_ptr->u); /* special command to controller BIOS */ icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); icph_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]); icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); icph_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; icph_delay(20); while (icph_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("initialization error\n"); icph_munmap(ha->brd); return 0; } icph_delay(1); } icph_writeb(0, &dp6c_ptr->u.ic.S_Status); #endif icp->icp_ic_all_size = ICP_PCINEW_SZ; icp->icp_copy_cmd = icp_pcinew_copy_cmd; icp->icp_get_status = icp_pcinew_get_status; icp->icp_intr = icp_pcinew_intr; icp->icp_release_event = icp_pcinew_release_event; icp->icp_set_sema0 = icp_pcinew_set_sema0; icp->icp_test_busy = icp_pcinew_test_busy; break; case ICP_MPR: bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC, ICP_MPR_MAGIC); if (bus_space_read_4(dpmemt, dpmemh, ICP_MPR_IC) != ICP_MPR_MAGIC) { aprint_error( "cannot access DPMEM at 0x%lx (shadowed?)\n", (u_long)dpmembase); goto bail_out; } /* * XXX Here the Linux driver has a weird remapping logic I * don't understand. My controller does not need it, and I * cannot see what purpose it serves, therefore I did not * do anything similar. */ bus_space_set_region_4(dpmemt, dpmemh, ICP_I960_SZ, 0, ICP_DPR_IF_SZ >> 2); /* Disable everything. */ bus_space_write_1(dpmemt, dpmemh, ICP_EDOOR_EN, bus_space_read_1(dpmemt, dpmemh, ICP_EDOOR_EN) | 4); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_EDOOR, 0xff); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS, 0); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_CMD_INDEX, 0); bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO, htole32(dpmembase)); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_CMD_INDX, 0xff); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_LDOOR, 1); DELAY(20); retries = 1000000; while (bus_space_read_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS) != 0xff) { if (--retries == 0) { aprint_error("DEINIT failed\n"); goto bail_out; } DELAY(1); } protocol = (u_int8_t)bus_space_read_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS, 0); if (protocol != ICP_PROTOCOL_VERSION) { aprint_error("unsupported protocol %d\n", protocol); goto bail_out; } /* special commnd to controller BIOS */ bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO, 0); bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO + sizeof(u_int32_t), 0); bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO + 2 * sizeof(u_int32_t), 1); bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO + 3 * sizeof(u_int32_t), 0); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_CMD_INDX, 0xfe); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_LDOOR, 1); DELAY(20); retries = 1000000; while (bus_space_read_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS) != 0xfe) { if (--retries == 0) { aprint_error("initialization error\n"); goto bail_out; } DELAY(1); } bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS, 0); icp->icp_copy_cmd = icp_mpr_copy_cmd; icp->icp_get_status = icp_mpr_get_status; icp->icp_intr = icp_mpr_intr; icp->icp_release_event = icp_mpr_release_event; icp->icp_set_sema0 = icp_mpr_set_sema0; icp->icp_test_busy = icp_mpr_test_busy; break; } if (pci_intr_map(pa, &ih)) { aprint_error("couldn't map interrupt\n"); goto bail_out; } intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf)); icp->icp_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, icp_intr, icp); if (icp->icp_ih == NULL) { aprint_error("couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); goto bail_out; } status |= INTR_ESTABLISHED; if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL) aprint_normal("Intel Storage RAID controller\n"); else aprint_normal("ICP-Vortex RAID controller\n"); icp->icp_pci_bus = pa->pa_bus; icp->icp_pci_device = pa->pa_device; icp->icp_pci_device_id = PCI_PRODUCT(pa->pa_id); icp->icp_pci_subdevice_id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); if (icp_init(icp, intrstr)) goto bail_out; icp_pci_enable_intr(icp); return; bail_out: if ((status & DPMEM_MAPPED) != 0) bus_space_unmap(dpmemt, dpmemh, dpmemsize); if ((status & IOMEM_MAPPED) != 0) bus_space_unmap(iomemt, iomemh, iomembase); if ((status & IO_MAPPED) != 0) bus_space_unmap(iot, ioh, iosize); if ((status & INTR_ESTABLISHED) != 0) pci_intr_disestablish(pa->pa_pc, icp->icp_ih); }