Mercurial > illumos > illumos-gate
changeset 5063:c7cb857a0196
6602421 panic in dca_encrypt() while handling an in-place call
author | gm89044 |
---|---|
date | Mon, 17 Sep 2007 08:01:53 -0700 |
parents | d04e7c32c7ca |
children | 0fbdaabf14a1 |
files | usr/src/uts/common/crypto/io/dca.c usr/src/uts/common/crypto/io/dca_3des.c usr/src/uts/common/crypto/io/dca_rsa.c |
diffstat | 3 files changed, 102 insertions(+), 70 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/crypto/io/dca.c Mon Sep 17 06:05:15 2007 -0700 +++ b/usr/src/uts/common/crypto/io/dca.c Mon Sep 17 08:01:53 2007 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -834,9 +834,9 @@ } crypto_prov_notify(WORKLIST(dca, MCR1)->dwl_prov, - CRYPTO_PROVIDER_READY); + CRYPTO_PROVIDER_READY); crypto_prov_notify(WORKLIST(dca, MCR2)->dwl_prov, - CRYPTO_PROVIDER_READY); + CRYPTO_PROVIDER_READY); /* Initialize the local random number pool for this instance */ if ((ret = dca_random_init(dca)) != CRYPTO_SUCCESS) { @@ -861,10 +861,12 @@ failed: /* unregister from the crypto framework */ if (WORKLIST(dca, MCR1)->dwl_prov != NULL) { - (void) crypto_unregister_provider(WORKLIST(dca, MCR1)->dwl_prov); + (void) crypto_unregister_provider( + WORKLIST(dca, MCR1)->dwl_prov); } if (WORKLIST(dca, MCR2)->dwl_prov != NULL) { - (void) crypto_unregister_provider(WORKLIST(dca, MCR2)->dwl_prov); + (void) crypto_unregister_provider( + WORKLIST(dca, MCR2)->dwl_prov); } if (intr_added) { CLRBIT(dca, CSR_DMACTL, @@ -928,19 +930,19 @@ * This needs to be done at the beginning of detach. */ if (WORKLIST(dca, MCR1)->dwl_prov != NULL) { - if (crypto_unregister_provider(WORKLIST(dca, MCR1)->dwl_prov) != - CRYPTO_SUCCESS) { - dca_error(dca, "unable to unregister MCR1 from kcf"); - return (DDI_FAILURE); - } + if (crypto_unregister_provider( + WORKLIST(dca, MCR1)->dwl_prov) != CRYPTO_SUCCESS) { + dca_error(dca, "unable to unregister MCR1 from kcf"); + return (DDI_FAILURE); + } } if (WORKLIST(dca, MCR2)->dwl_prov != NULL) { - if (crypto_unregister_provider(WORKLIST(dca, MCR2)->dwl_prov) != - CRYPTO_SUCCESS) { - dca_error(dca, "unable to unregister MCR2 from kcf"); - return (DDI_FAILURE); - } + if (crypto_unregister_provider( + WORKLIST(dca, MCR2)->dwl_prov) != CRYPTO_SUCCESS) { + dca_error(dca, "unable to unregister MCR2 from kcf"); + return (DDI_FAILURE); + } } /* @@ -1171,7 +1173,7 @@ */ wlp = WORKLIST(dca, MCR1); (void) sprintf(wlp->dwl_name, "dca%d:mcr1", - ddi_get_instance(dca->dca_dip)); + ddi_get_instance(dca->dca_dip)); wlp->dwl_lowater = ddi_getprop(DDI_DEV_T_ANY, dca->dca_dip, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "mcr1_lowater", MCR1LOWATER); @@ -1192,7 +1194,7 @@ */ wlp = WORKLIST(dca, MCR2); (void) sprintf(wlp->dwl_name, "dca%d:mcr2", - ddi_get_instance(dca->dca_dip)); + ddi_get_instance(dca->dca_dip)); wlp->dwl_lowater = ddi_getprop(DDI_DEV_T_ANY, dca->dca_dip, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "mcr2_lowater", MCR2LOWATER); @@ -1353,7 +1355,7 @@ * unqueue takes from the "tail" of the list, i.e. just before * the sentinel. */ - if ((node = q->dl_prev) == q) {; + if ((node = q->dl_prev) == q) { /* queue is empty */ return (NULL); } @@ -1985,6 +1987,10 @@ reqp->dr_chain_in_head.dc_buffer_paddr = 0; } + if (reqp->dr_flags & DR_INPLACE) { + return (rv); + } + /* Clear the output chain */ if (reqp->dr_chain_out_head.dc_buffer_paddr != NULL) { (void) ddi_dma_unbind_handle(reqp->dr_chain_out_dmah); @@ -2175,7 +2181,7 @@ /* if there isn't enough to do, don't bother now */ if ((wlp->dwl_count < wlp->dwl_reqspermcr) && (ddi_get_lbolt() < (wlp->dwl_lastsubmit + - drv_usectohz(MSEC)))) { + drv_usectohz(MSEC)))) { /* wait a bit longer... */ if (wlp->dwl_schedtid == 0) { wlp->dwl_schedtid = timeout(dca_schedtimeout, @@ -2294,7 +2300,7 @@ workp->dw_lbolt = ddi_get_lbolt(); /* Make sure MCR is synced out to device. */ (void) ddi_dma_sync(workp->dw_mcr_dmah, 0, 0, - DDI_DMA_SYNC_FORDEV); + DDI_DMA_SYNC_FORDEV); if (dca_check_dma_handle(dca, workp->dw_mcr_dmah, DCA_FM_ECLASS_NONE) != DDI_SUCCESS) { dca_destroywork(workp); @@ -2343,7 +2349,7 @@ /* only sync the MCR flags, since that's all we need */ (void) ddi_dma_sync(workp->dw_mcr_dmah, 0, 4, - DDI_DMA_SYNC_FORKERNEL); + DDI_DMA_SYNC_FORKERNEL); if (dca_check_dma_handle(dca, workp->dw_mcr_dmah, DCA_FM_ECLASS_NONE) != DDI_SUCCESS) { dca_rmqueue((dca_listnode_t *)workp); @@ -2537,15 +2543,7 @@ for (i = 0; i < wlp->dwl_reqspermcr; i++) { dca_request_t *reqp = workp->dw_reqs[i]; if (reqp) { - if (reqp->dr_flags & DR_INPLACE) { - dca_done(reqp, errno); - } else { - /* - * cause it to get retried - * elsewhere (software) - */ - dca_done(reqp, CRYPTO_FAILED); - } + dca_done(reqp, errno); workp->dw_reqs[i] = NULL; } } @@ -2875,7 +2873,8 @@ uiop = data->cd_uio; for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && off >= uiop->uio_iov[vec_idx].iov_len; - off -= uiop->uio_iov[vec_idx++].iov_len); + off -= uiop->uio_iov[vec_idx++].iov_len) + ; if (vec_idx == uiop->uio_iovcnt) { /* * The caller specified an offset that is larger than @@ -2913,7 +2912,8 @@ * Jump to the first mblk_t containing data to be processed. */ for (mp = data->cd_mp; mp != NULL && off >= MBLKL(mp); - off -= MBLKL(mp), mp = mp->b_cont); + off -= MBLKL(mp), mp = mp->b_cont) + ; if (mp == NULL) { /* * The caller specified an offset that is larger than @@ -3117,7 +3117,8 @@ uiop = in->cd_uio; for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && off >= uiop->uio_iov[vec_idx].iov_len; - off -= uiop->uio_iov[vec_idx++].iov_len); + off -= uiop->uio_iov[vec_idx++].iov_len) + ; if (vec_idx == uiop->uio_iovcnt) { /* * The caller specified an offset that is larger than @@ -3163,7 +3164,8 @@ * Jump to the first mblk_t containing data to be processed. */ for (mp = in->cd_mp; mp != NULL && off >= MBLKL(mp); - off -= MBLKL(mp), mp = mp->b_cont); + off -= MBLKL(mp), mp = mp->b_cont) + ; if (mp == NULL) { /* * The caller specified an offset that is larger than @@ -3266,7 +3268,8 @@ uiop = in->cd_uio; for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && off >= uiop->uio_iov[vec_idx].iov_len; - off -= uiop->uio_iov[vec_idx++].iov_len); + off -= uiop->uio_iov[vec_idx++].iov_len) + ; if (vec_idx == uiop->uio_iovcnt) { /* * The caller specified an offset that is larger than @@ -3306,7 +3309,8 @@ * Jump to the first mblk_t containing data to be processed. */ for (mp = in->cd_mp; mp != NULL && off >= MBLKL(mp); - off -= MBLKL(mp), mp = mp->b_cont); + off -= MBLKL(mp), mp = mp->b_cont) + ; if (mp == NULL) { /* * The caller specified an offset that is larger than @@ -3383,7 +3387,8 @@ uiop = out->cd_uio; for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && offset >= uiop->uio_iov[vec_idx].iov_len; - offset -= uiop->uio_iov[vec_idx++].iov_len); + offset -= uiop->uio_iov[vec_idx++].iov_len) + ; if (vec_idx == uiop->uio_iovcnt) { /* * The caller specified an offset that is larger than @@ -3428,7 +3433,8 @@ * Jump to the first mblk_t that can be written to. */ for (mp = out->cd_mp; mp != NULL && offset >= MBLKL(mp); - offset -= MBLKL(mp), mp = mp->b_cont); + offset -= MBLKL(mp), mp = mp->b_cont) + ; if (mp == NULL) { /* * The caller specified an offset that is larger than @@ -3740,6 +3746,13 @@ DCA_SOFTC_FROM_CTX(ctx, softc, instance); DBG(softc, DENTRY, "dca_encrypt: started"); + /* handle inplace ops */ + if (!ciphertext) { + dca_request_t *reqp = ctx->cc_provider_private; + reqp->dr_flags |= DR_INPLACE; + ciphertext = plaintext; + } + /* check mechanism */ switch (DCA_MECH_FROM_CTX(ctx)) { case DES_CBC_MECH_INFO_TYPE: @@ -3788,6 +3801,13 @@ DCA_SOFTC_FROM_CTX(ctx, softc, instance); DBG(softc, DENTRY, "dca_encrypt_update: started"); + /* handle inplace ops */ + if (!ciphertext) { + dca_request_t *reqp = ctx->cc_provider_private; + reqp->dr_flags |= DR_INPLACE; + ciphertext = plaintext; + } + /* check mechanism */ switch (DCA_MECH_FROM_CTX(ctx)) { case DES_CBC_MECH_INFO_TYPE: @@ -3862,6 +3882,11 @@ if (ctx_template != NULL) return (CRYPTO_ARGUMENTS_BAD); + /* handle inplace ops */ + if (!ciphertext) { + ciphertext = plaintext; + } + /* check mechanism */ switch (mechanism->cm_type) { case DES_CBC_MECH_INFO_TYPE: @@ -3955,6 +3980,13 @@ DCA_SOFTC_FROM_CTX(ctx, softc, instance); DBG(softc, DENTRY, "dca_decrypt: started"); + /* handle inplace ops */ + if (!plaintext) { + dca_request_t *reqp = ctx->cc_provider_private; + reqp->dr_flags |= DR_INPLACE; + plaintext = ciphertext; + } + /* check mechanism */ switch (DCA_MECH_FROM_CTX(ctx)) { case DES_CBC_MECH_INFO_TYPE: @@ -4004,6 +4036,13 @@ DCA_SOFTC_FROM_CTX(ctx, softc, instance); DBG(softc, DENTRY, "dca_decrypt_update: started"); + /* handle inplace ops */ + if (!plaintext) { + dca_request_t *reqp = ctx->cc_provider_private; + reqp->dr_flags |= DR_INPLACE; + plaintext = ciphertext; + } + /* check mechanism */ switch (DCA_MECH_FROM_CTX(ctx)) { case DES_CBC_MECH_INFO_TYPE: @@ -4078,6 +4117,11 @@ if (ctx_template != NULL) return (CRYPTO_ARGUMENTS_BAD); + /* handle inplace ops */ + if (!plaintext) { + plaintext = ciphertext; + } + /* check mechanism */ switch (mechanism->cm_type) { case DES_CBC_MECH_INFO_TYPE: @@ -4794,7 +4838,7 @@ /* Manufacturer ID */ (void) sprintf((char *)ext_info->ei_manufacturerID, "%s", - DCA_MANUFACTURER_ID); + DCA_MANUFACTURER_ID); len = strlen((char *)ext_info->ei_manufacturerID); (void) memset(ext_info->ei_manufacturerID + len, ' ', CRYPTO_EXT_SIZE_MANUF - len); @@ -4806,7 +4850,7 @@ len = strlen((char *)ext_info->ei_model); (void) memset(ext_info->ei_model + len, ' ', - CRYPTO_EXT_SIZE_MODEL - len); + CRYPTO_EXT_SIZE_MODEL - len); /* Serial Number. Blank for Deimos */ (void) memset(ext_info->ei_serial_number, ' ', CRYPTO_EXT_SIZE_SERIAL); @@ -4836,8 +4880,8 @@ { ddi_iblock_cookie_t fm_ibc; int fm_capabilities = DDI_FM_EREPORT_CAPABLE | - DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE | - DDI_FM_ERRCB_CAPABLE; + DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE | + DDI_FM_ERRCB_CAPABLE; /* Read FMA capabilities from dca.conf file (if present) */ dca->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, dca->dca_dip,
--- a/usr/src/uts/common/crypto/io/dca_3des.c Mon Sep 17 06:05:15 2007 -0700 +++ b/usr/src/uts/common/crypto/io/dca_3des.c Mon Sep 17 08:01:53 2007 -0700 @@ -21,7 +21,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -79,13 +79,6 @@ des_ctx->dr_ctx.iv[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7]; } - /* - * In-place operations (input == out) are indicated by having a - * NULL output. In this case set the output to point to the input. - */ - if (out == NULL) { - out = in; - } if (len > dca_length(out)) { DBG(dca, DWARN, "inadequate output space (need %d, got %d)", len, dca_length(out)); @@ -180,13 +173,6 @@ des_ctx->dr_ctx.iv[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7]; } - /* - * In-place operations (in == out) are indicated by having a - * NULL output. In this case set the output to point to the input. - */ - if (out == NULL) { - out = in; - } if (len > dca_length(out)) { DBG(dca, DWARN, "not enough output space (need %d, got %d)", len, dca_length(out)); @@ -346,6 +332,12 @@ */ ((dca_request_t *)ctx.cc_provider_private)->dr_ctx.atomic = 1; + /* check for inplace ops */ + if (input == output) { + ((dca_request_t *)ctx.cc_provider_private)->dr_flags + |= DR_INPLACE; + } + rv = dca_3des(&ctx, input, output, req, mode); if ((rv != CRYPTO_QUEUED) && (rv != CRYPTO_SUCCESS)) { DBG(NULL, DWARN, "dca_3desatomic: dca_3des() failed"); @@ -470,7 +462,7 @@ * Use the actual length if the first entry is sufficient. */ (void) ddi_dma_sync(reqp->dr_ibuf_dmah, 0, len, - DDI_DMA_SYNC_FORDEV); + DDI_DMA_SYNC_FORDEV); if (dca_check_dma_handle(dca, reqp->dr_ibuf_dmah, DCA_FM_ECLASS_NONE) != DDI_SUCCESS) { reqp->destroy = TRUE; @@ -529,7 +521,7 @@ if (reqp->dr_flags & DR_SCATTER) { (void) ddi_dma_sync(reqp->dr_obuf_dmah, 0, - reqp->dr_out_len, DDI_DMA_SYNC_FORKERNEL); + reqp->dr_out_len, DDI_DMA_SYNC_FORKERNEL); if (dca_check_dma_handle(reqp->dr_dca, reqp->dr_obuf_dmah, DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
--- a/usr/src/uts/common/crypto/io/dca_rsa.c Mon Sep 17 06:05:15 2007 -0700 +++ b/usr/src/uts/common/crypto/io/dca_rsa.c Mon Sep 17 08:01:53 2007 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -69,16 +69,6 @@ int rv = CRYPTO_QUEUED; int len; - /* - * In-place operations (in == out) are indicated by having a - * NULL output. In this case set the out to point to the in. - * Note that this only works for CKM_RSA_X_509 without any padding - */ - if (!out) { - DBG(dca, DWARN, "Using inline since output buffer is NULL."); - out = in; - } - /* We don't support non-contiguous buffers for RSA */ if (dca_sgcheck(dca, in, DCA_SG_CONTIG) || dca_sgcheck(dca, out, DCA_SG_CONTIG)) { @@ -661,6 +651,12 @@ */ ((dca_request_t *)ctx.cc_provider_private)->dr_ctx.atomic = 1; + /* check for inplace ops */ + if (input == output) { + ((dca_request_t *)ctx.cc_provider_private)->dr_flags + |= DR_INPLACE; + } + rv = dca_rsastart(&ctx, input, output, req, mode); /*