88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CDDL HEADER START
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm *
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The contents of this file are subject to the terms of the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Common Development and Distribution License (the "License").
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * You may not use this file except in compliance with the License.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm *
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * or http://www.opensolaris.org/os/licensing.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * See the License for the specific language governing permissions
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * and limitations under the License.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm *
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * When distributing Covered Code, include this CDDL HEADER in each
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If applicable, add the following below this CDDL HEADER, with the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * fields enclosed by brackets "[]" replaced with your own identifying
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * information: Portions Copyright [yyyy] [name of copyright owner]
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm *
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CDDL HEADER END
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
d8dd99136aadc95161b4031565b92214f8bbc8c8gm * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Use is subject to license terms.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#pragma ident "%Z%%M% %I% %E% SMI"
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Deimos - cryptographic acceleration based upon Broadcom 582x.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/types.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/ddi.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/sunddi.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/kmem.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/note.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/crypto/spi.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/crypto/dca.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic void dca_rsaverifydone(dca_request_t *, int);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic void dca_rsadone(dca_request_t *, int);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/* Exported function prototypes */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_rsastart(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_req_handle_t, int);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_rsainit(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, int);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmvoid dca_rsactxfree(void *);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_rsaatomic(crypto_provider_handle_t, crypto_session_id_t,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int, crypto_req_handle_t, int);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/* Local function prototypes */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int dca_pkcs1_padding(dca_t *dca, caddr_t buf, int flen, int tlen,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int private);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int dca_pkcs1_unpadding(char *buf, int *tlen, int flen, int mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int dca_x509_padding(caddr_t buf, int flen, int tlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int dca_x509_unpadding(char *buf, int tlen, int flen, int mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int decrypt_error_code(int mode, int decrypt, int verify, int def);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_rsastart(crypto_ctx_t *ctx, crypto_data_t *in, crypto_data_t *out,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_req_handle_t req, int mode)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *reqp = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_t *dca = ctx->cc_provider;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm caddr_t daddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv = CRYPTO_QUEUED;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* We don't support non-contiguous buffers for RSA */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_sgcheck(dca, in, DCA_SG_CONTIG) ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_sgcheck(dca, out, DCA_SG_CONTIG)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_NOT_SUPPORTED;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len = dca_length(in);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Extracting the key attributes is now done in dca_rsainit(). */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (mode == DCA_RSA_ENC || mode == DCA_RSA_SIGN ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm mode == DCA_RSA_SIGNR) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Return length needed to store the output.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For sign, sign-recover, and encrypt, the output buffer
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * should not be smaller than modlen since PKCS or X_509
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * padding will be applied
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_length(out) < reqp->dr_ctx.modlen) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsastart: output buffer too short (%d < %d)",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_length(out), reqp->dr_ctx.modlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length = reqp->dr_ctx.modlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_BUFFER_TOO_SMALL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (out != in && out->cd_length > reqp->dr_ctx.modlen)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length = reqp->dr_ctx.modlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* The input length should not be bigger than the modulus */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len > reqp->dr_ctx.modlen) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_LEN_RANGE,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SIGNATURE_LEN_RANGE, CRYPTO_DATA_LEN_RANGE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For decryption, verify, and verifyRecover, the input length should
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * not be less than the modulus
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len < reqp->dr_ctx.modlen && (mode == DCA_RSA_DEC ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm mode == DCA_RSA_VRFY || mode == DCA_RSA_VRFYR)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_LEN_RANGE,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SIGNATURE_LEN_RANGE, CRYPTO_DATA_LEN_RANGE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For decryption and verifyRecover, the output buffer should not
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * be less than the modulus
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (out->cd_length < reqp->dr_ctx.modlen && (mode == DCA_RSA_DEC ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm mode == DCA_RSA_VRFYR) &&
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.ctx_cm_type == RSA_X_509_MECH_INFO_TYPE) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length = reqp->dr_ctx.modlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_BUFFER_TOO_SMALL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* For decrypt and verify, the input should not be less than output */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (out && len < out->cd_length) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = decrypt_error_code(mode,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_ENCRYPTED_DATA_LEN_RANGE,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SIGNATURE_LEN_RANGE, CRYPTO_SUCCESS)) !=
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SUCCESS)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((daddr = dca_bufdaddr(in)) == NULL && len > 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_numcmp(daddr, len, (char *)reqp->dr_ctx.mod,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.modlen) > 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsastart: input larger (numerically) than modulus!");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SIGNATURE_INVALID, CRYPTO_DATA_INVALID);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_byte_stat = -1;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in = in;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out = out;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_kcf_req = req;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (mode == DCA_RSA_VRFY)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_callback = dca_rsaverifydone;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_callback = dca_rsadone;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(daddr, reqp->dr_ibuf_kaddr, len, reqp->dr_pkt_length);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (mode == DCA_RSA_ENC || mode == DCA_RSA_SIGN ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm mode == DCA_RSA_SIGNR) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Needs to pad appropriately for encrypt, sign, and
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * sign_recover
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.ctx_cm_type == RSA_PKCS_MECH_INFO_TYPE) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_pkcs1_padding(dca, reqp->dr_ibuf_kaddr,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len, reqp->dr_ctx.modlen, reqp->dr_ctx.pqfix)) !=
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_QUEUED)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else if (reqp->dr_ctx.ctx_cm_type ==
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm RSA_X_509_MECH_INFO_TYPE) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_x509_padding(reqp->dr_ibuf_kaddr,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len, reqp->dr_pkt_length)) != CRYPTO_QUEUED)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.mode = mode;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Since the max RSA input size is 256 bytes (2048 bits), the firstx
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * page (at least 4096 bytes) in the pre-mapped buffer is large enough.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Therefore, we use this first page for RSA.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_paddr = reqp->dr_ibuf_head.dc_buffer_paddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_next = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_len = reqp->dr_pkt_length;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_paddr = reqp->dr_obuf_head.dc_buffer_paddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_next = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_len = reqp->dr_pkt_length;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* schedule the work by doing a submit */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_start(dca, reqp, MCR2, 1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmerrout:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmvoid
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_rsadone(dca_request_t *reqp, int errno)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno == CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int outsz = reqp->dr_out->cd_length;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm caddr_t daddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) ddi_dma_sync(reqp->dr_obuf_dmah, 0, reqp->dr_out_len,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DDI_DMA_SYNC_FORKERNEL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_check_dma_handle(reqp->dr_dca, reqp->dr_obuf_dmah,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->destroy = TRUE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_DEVICE_ERROR;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.mode == DCA_RSA_DEC ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.mode == DCA_RSA_VRFY ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.mode == DCA_RSA_VRFYR) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Needs to unpad appropriately for decrypt, verify,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * and verify_recover
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.ctx_cm_type ==
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm RSA_PKCS_MECH_INFO_TYPE) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = dca_pkcs1_unpadding(
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_obuf_kaddr, &outsz,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.modlen, reqp->dr_ctx.mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* check for bad data errors */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno != CRYPTO_SUCCESS &&
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno != CRYPTO_BUFFER_TOO_SMALL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_bufdaddr(reqp->dr_out) == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_BUFFER_TOO_SMALL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno == CRYPTO_BUFFER_TOO_SMALL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out->cd_length = outsz;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Reset the output data length */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out->cd_length = outsz;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else if (reqp->dr_ctx.ctx_cm_type ==
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm RSA_X_509_MECH_INFO_TYPE) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((errno = dca_x509_unpadding(
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_obuf_kaddr, outsz,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_pkt_length, reqp->dr_ctx.mode)) !=
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SUCCESS)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((daddr = dca_bufdaddr(reqp->dr_out)) == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(reqp->dr_dca, DINTR,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsadone: reqp->dr_out is bad");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Note that there may be some number of null bytes
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * at the end of the source (result), but we don't care
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * about them -- they are place holders only and are
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * truncated here.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(reqp->dr_obuf_kaddr, daddr, outsz, outsz);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmerrout:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ASSERT(reqp->dr_kcf_req != NULL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* notify framework that request is completed */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_op_notification(reqp->dr_kcf_req, errno);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(reqp->dr_dca, DINTR,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsadone: returning 0x%x to the kef via crypto_op_notification",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For non-atomic operations, reqp will be freed in the kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * callback function since it may be needed again if
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CRYPTO_BUFFER_TOO_SMALL is returned to kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.atomic) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_ctx_t ctx;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx.cc_provider_private = reqp;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_rsactxfree(&ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmvoid
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_rsaverifydone(dca_request_t *reqp, int errno)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno == CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm char scratch[RSA_MAX_KEY_LEN];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int outsz = reqp->dr_out->cd_length;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm caddr_t daddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * ASSUMPTION: the signature length was already
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * checked on the way in, and it is a valid length.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) ddi_dma_sync(reqp->dr_obuf_dmah, 0, outsz,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DDI_DMA_SYNC_FORKERNEL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_check_dma_handle(reqp->dr_dca, reqp->dr_obuf_dmah,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->destroy = TRUE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_DEVICE_ERROR;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.mode == DCA_RSA_DEC ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.mode == DCA_RSA_VRFY ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.mode == DCA_RSA_VRFYR) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Needs to unpad appropriately for decrypt, verify,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * and verify_recover
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.ctx_cm_type ==
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm RSA_PKCS_MECH_INFO_TYPE) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = dca_pkcs1_unpadding(
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_obuf_kaddr, &outsz,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.modlen, reqp->dr_ctx.mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* check for bad data errors */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno != CRYPTO_SUCCESS &&
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno != CRYPTO_BUFFER_TOO_SMALL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_bufdaddr(reqp->dr_out) == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_BUFFER_TOO_SMALL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno == CRYPTO_BUFFER_TOO_SMALL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out->cd_length = outsz;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Reset the output data length */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out->cd_length = outsz;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else if (reqp->dr_ctx.ctx_cm_type ==
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm RSA_X_509_MECH_INFO_TYPE) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((errno = dca_x509_unpadding(
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_obuf_kaddr, outsz,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_pkt_length, reqp->dr_ctx.mode)) !=
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SUCCESS)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(reqp->dr_obuf_kaddr, scratch, outsz, outsz);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((daddr = dca_bufdaddr(reqp->dr_out)) == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_numcmp(daddr, reqp->dr_out->cd_length, scratch,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm outsz) != 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* VERIFY FAILED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_SIGNATURE_INVALID;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmerrout:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ASSERT(reqp->dr_kcf_req != NULL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* notify framework that request is completed */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_op_notification(reqp->dr_kcf_req, errno);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(reqp->dr_dca, DINTR,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsaverifydone: rtn 0x%x to the kef via crypto_op_notification",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For non-atomic operations, reqp will be freed in the kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * callback function since it may be needed again if
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CRYPTO_BUFFER_TOO_SMALL is returned to kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.atomic) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_ctx_t ctx;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx.cc_provider_private = reqp;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_rsactxfree(&ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Setup either a public or a private RSA key for subsequent uses
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_rsainit(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_key_t *key, int kmflag)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_object_attribute_t *attr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned expname = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm void *attrdata;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *exp;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *p;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *q;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *dp;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *dq;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *pinv;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned explen = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned plen = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned qlen = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned dplen = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned dqlen = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned pinvlen = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned modbits, expbits, pbits, qbits;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned modfix, expfix, pqfix = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uint16_t ctxlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm caddr_t kaddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *reqp = NULL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_t *dca = (dca_t *)ctx->cc_provider;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DENTRY, "dca_rsainit: start");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((reqp = dca_getreq(dca, MCR2, 1)) == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsainit: unable to allocate request for RSA");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_HOST_MEMORY;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.ctx_cm_type = mechanism->cm_type;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->cc_provider_private = reqp;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Key type can be either RAW, or REFERENCE, or ATTR_LIST (VALUE).
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Only ATTR_LIST is supported on Deimos for RSA.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((attr = dca_get_key_attr(key)) == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_rsainit: key attributes missing");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_KEY_TYPE_INCONSISTENT;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_find_attribute(attr, key->ck_count, CKA_PUBLIC_EXPONENT))
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm expname = CKA_PUBLIC_EXPONENT;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * RSA public key has only public exponent. RSA private key must have
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * private exponent. However, it may also have public exponent.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Thus, the existance of a private exponent indicates a private key.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_find_attribute(attr, key->ck_count, CKA_PRIVATE_EXPONENT))
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm expname = CKA_PRIVATE_EXPONENT;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (!expname) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_rsainit: no exponent in key");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Modulus */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_attr_lookup_uint8_array(attr, key->ck_count, CKA_MODULUS,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm &attrdata, &(reqp->dr_ctx.modlen))) != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_rsainit: failed to retrieve modulus");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((reqp->dr_ctx.modlen == 0) ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (reqp->dr_ctx.modlen > RSA_MAX_KEY_LEN)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_rsainit: bad modulus size");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((reqp->dr_ctx.mod = kmem_alloc(reqp->dr_ctx.modlen, kmflag)) ==
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_HOST_MEMORY;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm bcopy(attrdata, reqp->dr_ctx.mod, reqp->dr_ctx.modlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Exponent */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_attr_lookup_uint8_array(attr, key->ck_count, expname,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void **) &exp, &explen)) != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_rsainit: failed to retrieve exponent");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((explen == 0) || (explen > RSA_MAX_KEY_LEN)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_rsainit: bad exponent size");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Lookup private attributes */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (expname == CKA_PRIVATE_EXPONENT) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Prime 1 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_attr_lookup_uint8_array(attr, key->ck_count,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CKA_PRIME_1, (void **)&q, &qlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Prime 2 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_attr_lookup_uint8_array(attr, key->ck_count,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CKA_PRIME_2, (void **)&p, &plen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Exponent 1 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_attr_lookup_uint8_array(attr, key->ck_count,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CKA_EXPONENT_1, (void **)&dq, &dqlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Exponent 2 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_attr_lookup_uint8_array(attr, key->ck_count,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CKA_EXPONENT_2, (void **)&dp, &dplen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Coefficient */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_attr_lookup_uint8_array(attr, key->ck_count,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CKA_COEFFICIENT, (void **)&pinv, &pinvlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm modbits = dca_bitlen(reqp->dr_ctx.mod, reqp->dr_ctx.modlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm expbits = dca_bitlen(exp, explen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((modfix = dca_padfull(modbits)) == 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_rsainit: modulus too long");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_KEY_SIZE_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm expfix = ROUNDUP(explen, sizeof (uint32_t));
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (plen && qlen && dplen && dqlen && pinvlen) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned pfix, qfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm qbits = dca_bitlen(q, qlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm pbits = dca_bitlen(p, plen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm qfix = dca_padhalf(qbits);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm pfix = dca_padhalf(pbits);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (pfix & qfix)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm pqfix = max(pfix, qfix);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (pqfix) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_job_stat = DS_RSAPRIVATE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_pkt_length = 2 * pqfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_job_stat = DS_RSAPUBLIC;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_pkt_length = modfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (pqfix) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * NOTE: chip's notion of p vs. q is reversed from
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * PKCS#11. We use the chip's notion in our variable
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * naming.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctxlen = 8 + pqfix * 5;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* write out the context structure */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_CMD, CMD_RSAPRIVATE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_LENGTH, ctxlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* exponent and modulus length in bits!!! */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_RSAQLEN, qbits);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_RSAPLEN, pbits);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr = reqp->dr_ctx_kaddr + CTX_RSABIGNUMS;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* store the bignums */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(p, kaddr, plen, pqfix);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += pqfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(q, kaddr, qlen, pqfix);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += pqfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(dp, kaddr, dplen, pqfix);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += pqfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(dq, kaddr, dqlen, pqfix);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += pqfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(pinv, kaddr, pinvlen, pqfix);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += pqfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctxlen = 8 + modfix + expfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* write out the context structure */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_CMD, CMD_RSAPUBLIC);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_LENGTH, (uint16_t)ctxlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* exponent and modulus length in bits!!! */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_RSAEXPLEN, expbits);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_RSAMODLEN, modbits);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr = reqp->dr_ctx_kaddr + CTX_RSABIGNUMS;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* store the bignums */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(reqp->dr_ctx.mod, kaddr, reqp->dr_ctx.modlen,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm modfix);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += modfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(exp, kaddr, explen, expfix);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += expfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.pqfix = pqfix;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmerrout:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_SUCCESS)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_rsactxfree(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmvoid
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_rsactxfree(void *arg)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_ctx_t *ctx = (crypto_ctx_t *)arg;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *reqp = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp == NULL)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.mod)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kmem_free(reqp->dr_ctx.mod, reqp->dr_ctx.modlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.mode = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.ctx_cm_type = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.mod = NULL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.modlen = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.pqfix = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.atomic = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->destroy)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_destroyreq(reqp);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_freereq(reqp);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->cc_provider_private = NULL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_rsaatomic(crypto_provider_handle_t provider,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_key_t *key, crypto_data_t *input, crypto_data_t *output,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int kmflag, crypto_req_handle_t req, int mode)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_ctx_t ctx; /* on the stack */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx.cc_provider = provider;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx.cc_session = session_id;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_rsainit(&ctx, mechanism, key, kmflag);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_rsaatomic: dca_rsainit() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* The content of ctx should have been freed already */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Set the atomic flag so that the hardware callback function
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * will free the context.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ((dca_request_t *)ctx.cc_provider_private)->dr_ctx.atomic = 1;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
d8dd99136aadc95161b4031565b92214f8bbc8c8gm /* check for inplace ops */
d8dd99136aadc95161b4031565b92214f8bbc8c8gm if (input == output) {
d8dd99136aadc95161b4031565b92214f8bbc8c8gm ((dca_request_t *)ctx.cc_provider_private)->dr_flags
d8dd99136aadc95161b4031565b92214f8bbc8c8gm |= DR_INPLACE;
d8dd99136aadc95161b4031565b92214f8bbc8c8gm }
d8dd99136aadc95161b4031565b92214f8bbc8c8gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_rsastart(&ctx, input, output, req, mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The context will be freed in the hardware callback function if it
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * is queued
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_QUEUED)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_rsactxfree(&ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For RSA_PKCS padding and unpadding:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 1. The minimum padding is 11 bytes.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 2. The first and the last bytes must 0.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 3. The second byte is 1 for private and 2 for public keys.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 4. Pad with 0xff for private and non-zero random for public keys.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_pkcs1_padding(dca_t *dca, caddr_t buf, int flen, int tlen, int private)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int i;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DENTRY,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_pkcs1_padding: tlen: %d, flen: %d: private: %d\n",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm tlen, flen, private);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (flen > tlen - 11)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_DATA_LEN_RANGE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (private) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Padding for private encrypt */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm buf[flen] = '\0';
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (i = flen + 1; i < tlen - 2; i++) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm buf[i] = (unsigned char) 0xff;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm buf[tlen - 2] = 1;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm buf[tlen - 1] = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Padding for public encrypt */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm buf[flen] = '\0';
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_random_buffer(dca, &buf[flen+1], tlen - flen - 3) !=
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SUCCESS)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_RANDOM_NO_RNG);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm buf[tlen - 2] = 2;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm buf[tlen - 1] = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_QUEUED);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_pkcs1_unpadding(char *buf, int *tlen, int flen, int mode)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int i;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm const unsigned char *p;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned char type;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DENTRY, "dca_pkcs1_unpadding: tlen: %d, flen: %d\n",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm *tlen, flen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm p = (unsigned char *) buf + (flen-1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (*(p--) != 0)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SIGNATURE_INVALID, CRYPTO_DATA_INVALID);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* It is ok if the data length is 0 after removing the padding */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm type = *(p--);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (type == 01) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (i = flen - 3; i >= 0; i--) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (*p != 0xff) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (*p == '\0') {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm p--;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm break;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return decrypt_error_code(mode,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_ENCRYPTED_DATA_INVALID,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SIGNATURE_INVALID,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_DATA_INVALID);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm p--;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else if (type == 02) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (i = flen - 3; i >= 0; i--) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (*p == '\0') {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm p--;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm break;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm p--;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SIGNATURE_INVALID, CRYPTO_DATA_INVALID);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* i < 0 means did not find the end of the padding */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (i < 0)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SIGNATURE_INVALID, CRYPTO_DATA_INVALID);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (i > *tlen) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm *tlen = i;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_BUFFER_TOO_SMALL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (flen - i < 11)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return decrypt_error_code(mode,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_ENCRYPTED_DATA_LEN_RANGE,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SIGNATURE_LEN_RANGE, CRYPTO_DATA_LEN_RANGE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Return the unpadded length to the caller */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm *tlen = i;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_SUCCESS);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For RSA_X_509 padding and unpadding, pad all 0s before actual data.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Note that the data will be in reverse order.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_x509_padding(caddr_t buf, int flen, int tlen)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DENTRY, "dca_x509_padding: tlen: %d, flen: %d\n",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm tlen, flen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm bzero(buf+tlen, tlen - flen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_QUEUED);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/* ARGSUSED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_x509_unpadding(char *buf, int tlen, int flen, int mode)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int i;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm const unsigned char *p;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DENTRY, "dca_x509_unpadding: tlen: %d, flen: %d\n",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm tlen, flen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm p = (unsigned char *) buf + flen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (i = tlen; i < flen; i++) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (*(--p) != 0)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_SIGNATURE_INVALID);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_SUCCESS);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int decrypt_error_code(int mode, int decrypt, int verify, int def)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm switch (mode) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm case DCA_RSA_DEC:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (decrypt);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm case DCA_RSA_VRFY:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm case DCA_RSA_VRFYR:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (verify);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm default:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (def);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}