Exemplo n.º 1
0
/* This function is called from an interrupt handler */
void
nlm_xlprsaecc_msgring_handler(int vc, int size, int code, int src_id,
    struct nlm_fmn_msg *msg, void *data)
{
	struct xlp_rsa_command *cmd;
	struct xlp_rsa_softc *sc;
	struct crparam *outparam;
	int ostart;

	KASSERT(code == FMN_SWCODE_RSA,
	    ("%s: bad code = %d, expected code = %d\n", __func__, code,
	    FMN_SWCODE_RSA));

	sc = data;
	KASSERT(src_id >= sc->rsaecc_vc_start && src_id <= sc->rsaecc_vc_end,
	    ("%s: bad src_id = %d, expect %d - %d\n", __func__,
	    src_id, sc->rsaecc_vc_start, sc->rsaecc_vc_end));

	cmd = (struct xlp_rsa_command *)(uintptr_t)msg->msg[1];
	KASSERT(cmd != NULL, ("%s:cmd not received properly\n", __func__));

	if (RSA_ERROR(msg->msg[0]) != 0) {
		printf("%s: Message rcv msg0 %llx msg1 %llx err %x \n",
		    __func__, (unsigned long long)msg->msg[0],
		    (unsigned long long)msg->msg[1],
		    (int)RSA_ERROR(msg->msg[0]));
		cmd->krp->krp_status = EBADMSG;
	}

	if (cmd->krp != NULL) {
		ostart = cmd->krp->krp_iparams;
		outparam = &cmd->krp->krp_param[ostart];
		xlp_rsa_inp2hwformat(cmd->rsasrc + cmd->rsaopsize * ostart,
		    outparam->crp_p,
		    howmany(outparam->crp_nbits, 8),
		    1);
		crypto_kdone(cmd->krp);
	}

	xlp_free_cmd_params(cmd);
}
Exemplo n.º 2
0
static int
xlp_rsa_kprocess(device_t dev, struct cryptkop *krp, int hint)
{
	struct xlp_rsa_softc *sc = device_get_softc(dev);
	struct xlp_rsa_command *cmd;
	struct crparam *kp;
	int err, i;

	if (krp == NULL || krp->krp_callback == NULL)
		return (EINVAL);

	cmd = malloc(sizeof(struct xlp_rsa_command), M_DEVBUF,
	    M_NOWAIT | M_ZERO);
	KASSERT(cmd != NULL, ("%s:cmd is NULL\n", __func__));
	cmd->krp = krp;

#ifdef NLM_RSA_DEBUG
	print_krp_params(krp);
#endif
	err = EOPNOTSUPP;
	switch (krp->krp_op) {
	case CRK_MOD_EXP:
		if (krp->krp_iparams == 3 && krp->krp_oparams == 1)
			break;
		goto errout;
	default:
		device_printf(dev, "Op:%d not yet supported\n", krp->krp_op);
		goto errout;
	}

	err = xlp_get_rsa_opsize(cmd,
	    krp->krp_param[krp->krp_iparams - 1].crp_nbits);
	if (err != 0) {
		err = EINVAL;
		goto errout;
	}
	cmd->rsafn = 0; /* Mod Exp */
	cmd->rsasrc = malloc(
	    cmd->rsaopsize * (krp->krp_iparams + krp->krp_oparams),
	    M_DEVBUF,
	    M_NOWAIT | M_ZERO);
	if (cmd->rsasrc == NULL) {
		err = ENOMEM;
		goto errout;
	}

	for (i = 0, kp = krp->krp_param; i < krp->krp_iparams; i++, kp++) {
		KASSERT(kp->crp_nbits != 0,
		    ("%s: parameter[%d]'s length is zero\n", __func__, i));
		xlp_rsa_inp2hwformat(kp->crp_p,
		    cmd->rsasrc + i * cmd->rsaopsize,
		    howmany(kp->crp_nbits, 8), 0);
	}
	err = nlm_crypto_complete_rsa_request(sc, cmd);
	if (err != 0)
		goto errout;

	return (0);
errout:
	xlp_free_cmd_params(cmd);
	krp->krp_status = err;
	crypto_kdone(krp);
	return (err);
}
Exemplo n.º 3
0
static int
xlp_sec_process(device_t dev, struct cryptop *crp, int hint)
{
	struct xlp_sec_softc *sc = device_get_softc(dev);
	struct xlp_sec_command *cmd = NULL;
	int session, err = -1, ret = 0;
	struct cryptodesc *crd1, *crd2;
	struct xlp_sec_session *ses;
	unsigned int nsegs = 0;

	if (crp == NULL || crp->crp_callback == NULL) {
		return (EINVAL);
	}
	session = XLP_SEC_SESSION(crp->crp_sid);
	if (sc == NULL || session >= sc->sc_nsessions) {
		err = EINVAL;
		goto errout;
	}
	ses = &sc->sc_sessions[session];

	if ((cmd = malloc(sizeof(struct xlp_sec_command), M_DEVBUF,
	    M_NOWAIT | M_ZERO)) == NULL) {
		err = ENOMEM;
		goto errout;
	}

	cmd->crp = crp;
	cmd->session_num = session;
	cmd->hash_dst_len = ses->hs_mlen;

	if ((crd1 = crp->crp_desc) == NULL) {
		err = EINVAL;
		goto errout;
	}
	crd2 = crd1->crd_next;

	if ((ret = xlp_get_nsegs(crp, &nsegs)) != 0) {
		err = EINVAL;
		goto errout;
	}
	if (((crd1 != NULL) && (crd1->crd_flags & CRD_F_IV_EXPLICIT)) ||
	    ((crd2 != NULL) && (crd2->crd_flags & CRD_F_IV_EXPLICIT))) {
		/* Since IV is given as separate segment to avoid copy */
		nsegs += 1;
	}
	cmd->nsegs = nsegs;

	if ((err = xlp_alloc_cmd_params(cmd, nsegs)) != 0)
		goto errout;

	if ((crd1 != NULL) && (crd2 == NULL)) {
		if (crd1->crd_alg == CRYPTO_DES_CBC ||
		    crd1->crd_alg == CRYPTO_3DES_CBC ||
		    crd1->crd_alg == CRYPTO_AES_CBC ||
		    crd1->crd_alg == CRYPTO_ARC4) {
			cmd->enccrd = crd1;
			cmd->maccrd = NULL;
			if ((ret = nlm_get_cipher_param(cmd)) != 0) {
				err = EINVAL;
				goto errout;
			}
			if (crd1->crd_flags & CRD_F_IV_EXPLICIT)
				cmd->cipheroff = cmd->ivlen;
			else 
				cmd->cipheroff = cmd->enccrd->crd_skip;
			cmd->cipherlen = cmd->enccrd->crd_len;
			if (crd1->crd_flags & CRD_F_IV_PRESENT)
				cmd->ivoff  = 0;
			else
				cmd->ivoff  = cmd->enccrd->crd_inject;
			if ((err = xlp_copyiv(sc, cmd, cmd->enccrd)) != 0)
				goto errout;
			if ((err = nlm_crypto_do_cipher(sc, cmd)) != 0)
				goto errout;
		} else if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
		    crd1->crd_alg == CRYPTO_SHA1 ||
		    crd1->crd_alg == CRYPTO_MD5) {
			cmd->enccrd = NULL;
			cmd->maccrd = crd1;
			if ((ret = nlm_get_digest_param(cmd)) != 0) {
				err = EINVAL;
				goto errout;
			}
			cmd->hashoff = cmd->maccrd->crd_skip;
			cmd->hashlen = cmd->maccrd->crd_len;
			cmd->hmacpad = 0;
			cmd->hashsrc = 0;
			if ((err = nlm_crypto_do_digest(sc, cmd)) != 0)
				goto errout;
		} else {
			err = EINVAL;
			goto errout;
		}
	} else if( (crd1 != NULL) && (crd2 != NULL) ) {
		if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
		    crd1->crd_alg == CRYPTO_MD5 ||
		    crd1->crd_alg == CRYPTO_SHA1) &&
		    (crd2->crd_alg == CRYPTO_DES_CBC ||
		    crd2->crd_alg == CRYPTO_3DES_CBC ||
		    crd2->crd_alg == CRYPTO_AES_CBC ||
		    crd2->crd_alg == CRYPTO_ARC4)) {
			cmd->maccrd = crd1;
			cmd->enccrd = crd2;
		} else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
		    crd1->crd_alg == CRYPTO_ARC4 ||
		    crd1->crd_alg == CRYPTO_3DES_CBC ||
		    crd1->crd_alg == CRYPTO_AES_CBC) &&
		    (crd2->crd_alg == CRYPTO_MD5_HMAC ||
		    crd2->crd_alg == CRYPTO_SHA1_HMAC ||
		    crd2->crd_alg == CRYPTO_MD5 ||
		    crd2->crd_alg == CRYPTO_SHA1)) {
			cmd->enccrd = crd1;
			cmd->maccrd = crd2;
		} else {
			err = EINVAL;
			goto errout;
		}
		if ((ret = nlm_get_cipher_param(cmd)) != 0) {
			err = EINVAL;
			goto errout;
		}
		if ((ret = nlm_get_digest_param(cmd)) != 0) {
			err = EINVAL;
			goto errout;
		}
		cmd->ivoff  = cmd->enccrd->crd_inject;
		cmd->hashoff = cmd->maccrd->crd_skip;
		cmd->hashlen = cmd->maccrd->crd_len;
		cmd->hmacpad = 0;
		if (cmd->enccrd->crd_flags & CRD_F_ENCRYPT)
			cmd->hashsrc = 1;
		else
			cmd->hashsrc = 0;
		cmd->cipheroff = cmd->enccrd->crd_skip;
		cmd->cipherlen = cmd->enccrd->crd_len;
		if ((err = xlp_copyiv(sc, cmd, cmd->enccrd)) != 0)
			goto errout;
		if ((err = nlm_crypto_do_cipher_digest(sc, cmd)) != 0)
			goto errout;
	} else {
		err = EINVAL;
		goto errout;
	}
	return (0);
errout:
	xlp_free_cmd_params(cmd);
	if (err == ERESTART) {
		sc->sc_needwakeup |= CRYPTO_SYMQ;
		creditleft = 0;
		return (err);
	}
	crp->crp_etype = err;
	crypto_done(crp);
	return (err);
}
Exemplo n.º 4
0
static int 
xlp_rsa_init(struct xlp_rsa_softc *sc, int node)
{
	struct xlp_rsa_command *cmd = NULL;
	uint32_t fbvc, dstvc, endsel, regval;
	struct nlm_fmn_msg m;
	int err, ret, i;
	uint64_t base;

	/* Register interrupt handler for the RSA/ECC CMS messages */
	if (register_msgring_handler(sc->rsaecc_vc_start,
	    sc->rsaecc_vc_end, nlm_xlprsaecc_msgring_handler, sc) != 0) {
		err = -1;
		printf("Couldn't register rsa/ecc msgring handler\n");
		goto errout;
	}
	fbvc = nlm_cpuid() * 4 + XLPGE_FB_VC;
	/* Do the CMS credit initialization */
	/* Currently it is configured by default to 50 when kernel comes up */

#if BYTE_ORDER == LITTLE_ENDIAN
	for (i = 0; i < nitems(nlm_rsa_ucode_data); i++)
		nlm_rsa_ucode_data[i] = htobe64(nlm_rsa_ucode_data[i]);
#endif
	for (dstvc = sc->rsaecc_vc_start; dstvc <= sc->rsaecc_vc_end; dstvc++) {
		cmd = malloc(sizeof(struct xlp_rsa_command), M_DEVBUF,
		    M_NOWAIT | M_ZERO);
		KASSERT(cmd != NULL, ("%s:cmd is NULL\n", __func__));
		cmd->rsasrc = contigmalloc(sizeof(nlm_rsa_ucode_data),
		    M_DEVBUF,
		    (M_WAITOK | M_ZERO),
		    0UL /* low address */, -1UL /* high address */,
		    XLP_L2L3_CACHELINE_SIZE /* alignment */,
		    0UL /* boundary */);
		KASSERT(cmd->rsasrc != NULL,
		    ("%s:cmd->rsasrc is NULL\n", __func__));
		memcpy(cmd->rsasrc, nlm_rsa_ucode_data,
		    sizeof(nlm_rsa_ucode_data));
		m.msg[0] = nlm_crypto_form_rsa_ecc_fmn_entry0(1, 0x70, 0,
		    vtophys(cmd->rsasrc));
		m.msg[1] = nlm_crypto_form_rsa_ecc_fmn_entry1(0, 1, fbvc,
		    vtophys(cmd->rsasrc));
		/* Software scratch pad */
		m.msg[2] = (uintptr_t)cmd;
		m.msg[3] = 0;

		ret = nlm_fmn_msgsend(dstvc, 3, FMN_SWCODE_RSA, &m);
		if (ret != 0) {
			err = -1;
			printf("%s: msgsnd failed (%x)\n", __func__, ret);
			goto errout;
		}
	}
	/* Configure so that all VCs send request to all RSA pipes */
	base = nlm_get_rsa_regbase(node);
	if (nlm_is_xlp3xx()) {
		endsel = 1;
		regval = 0xFFFF;
	} else {
		endsel = 3;
		regval = 0x07FFFFFF;
	}
	for (i = 0; i < endsel; i++)
		nlm_write_rsa_reg(base, RSA_ENG_SEL_0 + i, regval);
	return (0);
errout:
	xlp_free_cmd_params(cmd);
	return (err);
}
Exemplo n.º 5
0
/* This function is called from an interrupt handler */
void
nlm_xlpsec_msgring_handler(int vc, int size, int code, int src_id,
    struct nlm_fmn_msg *msg, void *data)
{
	struct xlp_sec_command *cmd = NULL;
	struct xlp_sec_softc *sc = NULL;
	struct cryptodesc *crd = NULL;
	unsigned int ivlen = 0;

	KASSERT(code == FMN_SWCODE_CRYPTO,
	    ("%s: bad code = %d, expected code = %d\n", __FUNCTION__,
	    code, FMN_SWCODE_CRYPTO));

	sc = (struct xlp_sec_softc *)data;
	KASSERT(src_id >= sc->sec_vc_start && src_id <= sc->sec_vc_end,
	    ("%s: bad src_id = %d, expect %d - %d\n", __FUNCTION__,
	    src_id, sc->sec_vc_start, sc->sec_vc_end));

	cmd = (struct xlp_sec_command *)(uintptr_t)msg->msg[0];
	KASSERT(cmd != NULL && cmd->crp != NULL,
		("%s :cmd not received properly\n",__FUNCTION__));

	KASSERT(CRYPTO_ERROR(msg->msg[1]) == 0,
	    ("%s: Message rcv msg0 %llx msg1 %llx err %x \n", __FUNCTION__,
	    (unsigned long long)msg->msg[0], (unsigned long long)msg->msg[1],
	    (int)CRYPTO_ERROR(msg->msg[1])));

	crd = cmd->enccrd;
	/* Copy the last 8 or 16 bytes to the session iv, so that in few
	 * cases this will be used as IV for the next request
	 */
	if (crd != NULL) {
		if ((crd->crd_alg == CRYPTO_DES_CBC ||
		    crd->crd_alg == CRYPTO_3DES_CBC ||
		    crd->crd_alg == CRYPTO_AES_CBC) &&
		    (crd->crd_flags & CRD_F_ENCRYPT)) {
			ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ?
			    XLP_SEC_AES_IV_LENGTH : XLP_SEC_DES_IV_LENGTH);
			crypto_copydata(cmd->crp->crp_flags, cmd->crp->crp_buf,
			    crd->crd_skip + crd->crd_len - ivlen, ivlen,
			    sc->sc_sessions[cmd->session_num].ses_iv);
		}
	}

	/* If there are not enough credits to send, then send request
	 * will fail with ERESTART and the driver will be blocked until it is
	 * unblocked here after knowing that there are sufficient credits to
	 * send the request again.
	 */
	if (sc->sc_needwakeup) {
		atomic_add_int(&creditleft, sc->sec_msgsz);
		if (creditleft >= (NLM_CRYPTO_LEFT_REQS)) {
			crypto_unblock(sc->sc_cid, sc->sc_needwakeup);
			sc->sc_needwakeup &= (~(CRYPTO_SYMQ | CRYPTO_ASYMQ));
		}
	}
	if(cmd->maccrd) {
		crypto_copyback(cmd->crp->crp_flags,
		    cmd->crp->crp_buf, cmd->maccrd->crd_inject,
		    cmd->hash_dst_len, cmd->hashdest);
	}

	/* This indicates completion of the crypto operation */
	crypto_done(cmd->crp);

	xlp_free_cmd_params(cmd);

	return;
}