xref: /onnv-gate/usr/src/uts/common/crypto/io/dca_rsa.c (revision 906:1b5a12bcb15b)
1*906Sgm89044 /*
2*906Sgm89044  * CDDL HEADER START
3*906Sgm89044  *
4*906Sgm89044  * The contents of this file are subject to the terms of the
5*906Sgm89044  * Common Development and Distribution License (the "License").
6*906Sgm89044  * You may not use this file except in compliance with the License.
7*906Sgm89044  *
8*906Sgm89044  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*906Sgm89044  * or http://www.opensolaris.org/os/licensing.
10*906Sgm89044  * See the License for the specific language governing permissions
11*906Sgm89044  * and limitations under the License.
12*906Sgm89044  *
13*906Sgm89044  * When distributing Covered Code, include this CDDL HEADER in each
14*906Sgm89044  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*906Sgm89044  * If applicable, add the following below this CDDL HEADER, with the
16*906Sgm89044  * fields enclosed by brackets "[]" replaced with your own identifying
17*906Sgm89044  * information: Portions Copyright [yyyy] [name of copyright owner]
18*906Sgm89044  *
19*906Sgm89044  * CDDL HEADER END
20*906Sgm89044  */
21*906Sgm89044 
22*906Sgm89044 /*
23*906Sgm89044  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*906Sgm89044  * Use is subject to license terms.
25*906Sgm89044  */
26*906Sgm89044 
27*906Sgm89044 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*906Sgm89044 
29*906Sgm89044 /*
30*906Sgm89044  * Deimos - cryptographic acceleration based upon Broadcom 582x.
31*906Sgm89044  */
32*906Sgm89044 
33*906Sgm89044 #include <sys/types.h>
34*906Sgm89044 #include <sys/ddi.h>
35*906Sgm89044 #include <sys/sunddi.h>
36*906Sgm89044 #include <sys/kmem.h>
37*906Sgm89044 #include <sys/note.h>
38*906Sgm89044 #include <sys/crypto/common.h>
39*906Sgm89044 #include <sys/crypto/spi.h>
40*906Sgm89044 #include <sys/crypto/ioctl.h>
41*906Sgm89044 #include <sys/crypto/dca.h>
42*906Sgm89044 
43*906Sgm89044 
44*906Sgm89044 static void dca_rsaverifydone(dca_request_t *, int);
45*906Sgm89044 static void dca_rsadone(dca_request_t *, int);
46*906Sgm89044 
47*906Sgm89044 /* Exported function prototypes */
48*906Sgm89044 int dca_rsastart(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
49*906Sgm89044     crypto_req_handle_t, int);
50*906Sgm89044 int dca_rsainit(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, int);
51*906Sgm89044 void dca_rsactxfree(void *);
52*906Sgm89044 int dca_rsaatomic(crypto_provider_handle_t, crypto_session_id_t,
53*906Sgm89044     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
54*906Sgm89044     int, crypto_req_handle_t, int);
55*906Sgm89044 
56*906Sgm89044 /* Local function prototypes */
57*906Sgm89044 static int dca_pkcs1_padding(dca_t *dca, caddr_t buf, int flen, int tlen,
58*906Sgm89044     int private);
59*906Sgm89044 static int dca_pkcs1_unpadding(char *buf, int *tlen, int flen, int mode);
60*906Sgm89044 static int dca_x509_padding(caddr_t buf, int flen, int tlen);
61*906Sgm89044 static int dca_x509_unpadding(char *buf, int tlen, int flen, int mode);
62*906Sgm89044 static int decrypt_error_code(int mode, int decrypt, int verify, int def);
63*906Sgm89044 
64*906Sgm89044 
65*906Sgm89044 int dca_rsastart(crypto_ctx_t *ctx, crypto_data_t *in, crypto_data_t *out,
66*906Sgm89044     crypto_req_handle_t req, int mode)
67*906Sgm89044 {
68*906Sgm89044 	dca_request_t		*reqp = ctx->cc_provider_private;
69*906Sgm89044 	dca_t			*dca = ctx->cc_provider;
70*906Sgm89044 	caddr_t			daddr;
71*906Sgm89044 	int			rv = CRYPTO_QUEUED;
72*906Sgm89044 	int			len;
73*906Sgm89044 
74*906Sgm89044 	/*
75*906Sgm89044 	 * In-place operations (in == out) are indicated by having a
76*906Sgm89044 	 * NULL output. In this case set the out to point to the in.
77*906Sgm89044 	 * Note that this only works for CKM_RSA_X_509 without any padding
78*906Sgm89044 	 */
79*906Sgm89044 	if (!out) {
80*906Sgm89044 		DBG(dca, DWARN, "Using inline since output buffer is NULL.");
81*906Sgm89044 		out = in;
82*906Sgm89044 	}
83*906Sgm89044 
84*906Sgm89044 	/* We don't support non-contiguous buffers for RSA */
85*906Sgm89044 	if (dca_sgcheck(dca, in, DCA_SG_CONTIG) ||
86*906Sgm89044 	    dca_sgcheck(dca, out, DCA_SG_CONTIG)) {
87*906Sgm89044 		rv = CRYPTO_NOT_SUPPORTED;
88*906Sgm89044 		goto errout;
89*906Sgm89044 	}
90*906Sgm89044 
91*906Sgm89044 	len = dca_length(in);
92*906Sgm89044 
93*906Sgm89044 	/* Extracting the key attributes is now done in dca_rsainit(). */
94*906Sgm89044 	if (mode == DCA_RSA_ENC || mode == DCA_RSA_SIGN ||
95*906Sgm89044 	    mode == DCA_RSA_SIGNR) {
96*906Sgm89044 		/*
97*906Sgm89044 		 * Return length needed to store the output.
98*906Sgm89044 		 * For sign, sign-recover, and encrypt, the output buffer
99*906Sgm89044 		 * should not be smaller than modlen since PKCS or X_509
100*906Sgm89044 		 * padding will be applied
101*906Sgm89044 		 */
102*906Sgm89044 		if (dca_length(out) < reqp->dr_ctx.modlen) {
103*906Sgm89044 			DBG(dca, DWARN,
104*906Sgm89044 			    "dca_rsastart: output buffer too short (%d < %d)",
105*906Sgm89044 			    dca_length(out), reqp->dr_ctx.modlen);
106*906Sgm89044 			out->cd_length = reqp->dr_ctx.modlen;
107*906Sgm89044 			rv = CRYPTO_BUFFER_TOO_SMALL;
108*906Sgm89044 			goto errout;
109*906Sgm89044 		}
110*906Sgm89044 	}
111*906Sgm89044 	if (out != in && out->cd_length > reqp->dr_ctx.modlen)
112*906Sgm89044 		out->cd_length = reqp->dr_ctx.modlen;
113*906Sgm89044 
114*906Sgm89044 	/* The input length should not be bigger than the modulus */
115*906Sgm89044 	if (len > reqp->dr_ctx.modlen) {
116*906Sgm89044 		rv = decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_LEN_RANGE,
117*906Sgm89044 		    CRYPTO_SIGNATURE_LEN_RANGE, CRYPTO_DATA_LEN_RANGE);
118*906Sgm89044 		goto errout;
119*906Sgm89044 	}
120*906Sgm89044 
121*906Sgm89044 	/*
122*906Sgm89044 	 * For decryption, verify, and verifyRecover, the input length should
123*906Sgm89044 	 * not be less than the modulus
124*906Sgm89044 	 */
125*906Sgm89044 	if (len < reqp->dr_ctx.modlen && (mode == DCA_RSA_DEC ||
126*906Sgm89044 	    mode == DCA_RSA_VRFY || mode == DCA_RSA_VRFYR)) {
127*906Sgm89044 		rv = decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_LEN_RANGE,
128*906Sgm89044 		    CRYPTO_SIGNATURE_LEN_RANGE, CRYPTO_DATA_LEN_RANGE);
129*906Sgm89044 		goto errout;
130*906Sgm89044 	}
131*906Sgm89044 
132*906Sgm89044 	/*
133*906Sgm89044 	 * For decryption and verifyRecover, the output buffer should not
134*906Sgm89044 	 * be less than the modulus
135*906Sgm89044 	 */
136*906Sgm89044 	if (out->cd_length < reqp->dr_ctx.modlen && (mode == DCA_RSA_DEC ||
137*906Sgm89044 	    mode == DCA_RSA_VRFYR) &&
138*906Sgm89044 	    reqp->dr_ctx.ctx_cm_type == RSA_X_509_MECH_INFO_TYPE) {
139*906Sgm89044 		out->cd_length = reqp->dr_ctx.modlen;
140*906Sgm89044 		rv = CRYPTO_BUFFER_TOO_SMALL;
141*906Sgm89044 		goto errout;
142*906Sgm89044 	}
143*906Sgm89044 
144*906Sgm89044 	/* For decrypt and verify, the input should not be less than output */
145*906Sgm89044 	if (out && len < out->cd_length) {
146*906Sgm89044 		if ((rv = decrypt_error_code(mode,
147*906Sgm89044 		    CRYPTO_ENCRYPTED_DATA_LEN_RANGE,
148*906Sgm89044 		    CRYPTO_SIGNATURE_LEN_RANGE, CRYPTO_SUCCESS)) !=
149*906Sgm89044 		    CRYPTO_SUCCESS)
150*906Sgm89044 			goto errout;
151*906Sgm89044 	}
152*906Sgm89044 
153*906Sgm89044 	if ((daddr = dca_bufdaddr(in)) == NULL && len > 0) {
154*906Sgm89044 		rv = CRYPTO_ARGUMENTS_BAD;
155*906Sgm89044 		goto errout;
156*906Sgm89044 	}
157*906Sgm89044 
158*906Sgm89044 	if (dca_numcmp(daddr, len, (char *)reqp->dr_ctx.mod,
159*906Sgm89044 	    reqp->dr_ctx.modlen) > 0) {
160*906Sgm89044 		DBG(dca, DWARN,
161*906Sgm89044 		    "dca_rsastart: input larger (numerically) than modulus!");
162*906Sgm89044 		rv = decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
163*906Sgm89044 		    CRYPTO_SIGNATURE_INVALID, CRYPTO_DATA_INVALID);
164*906Sgm89044 		goto errout;
165*906Sgm89044 	}
166*906Sgm89044 
167*906Sgm89044 	reqp->dr_byte_stat = -1;
168*906Sgm89044 	reqp->dr_in = in;
169*906Sgm89044 	reqp->dr_out = out;
170*906Sgm89044 	reqp->dr_kcf_req = req;
171*906Sgm89044 	if (mode == DCA_RSA_VRFY)
172*906Sgm89044 		reqp->dr_callback = dca_rsaverifydone;
173*906Sgm89044 	else
174*906Sgm89044 		reqp->dr_callback = dca_rsadone;
175*906Sgm89044 
176*906Sgm89044 	dca_reverse(daddr, reqp->dr_ibuf_kaddr, len, reqp->dr_pkt_length);
177*906Sgm89044 	if (mode == DCA_RSA_ENC || mode == DCA_RSA_SIGN ||
178*906Sgm89044 	    mode == DCA_RSA_SIGNR) {
179*906Sgm89044 		/*
180*906Sgm89044 		 * Needs to pad appropriately for encrypt, sign, and
181*906Sgm89044 		 * sign_recover
182*906Sgm89044 		 */
183*906Sgm89044 		if (reqp->dr_ctx.ctx_cm_type == RSA_PKCS_MECH_INFO_TYPE) {
184*906Sgm89044 			if ((rv = dca_pkcs1_padding(dca, reqp->dr_ibuf_kaddr,
185*906Sgm89044 			    len, reqp->dr_ctx.modlen, reqp->dr_ctx.pqfix)) !=
186*906Sgm89044 			    CRYPTO_QUEUED)
187*906Sgm89044 				goto errout;
188*906Sgm89044 		} else if (reqp->dr_ctx.ctx_cm_type ==
189*906Sgm89044 		    RSA_X_509_MECH_INFO_TYPE) {
190*906Sgm89044 			if ((rv = dca_x509_padding(reqp->dr_ibuf_kaddr,
191*906Sgm89044 			    len, reqp->dr_pkt_length)) != CRYPTO_QUEUED)
192*906Sgm89044 				goto errout;
193*906Sgm89044 		}
194*906Sgm89044 	}
195*906Sgm89044 	reqp->dr_ctx.mode = mode;
196*906Sgm89044 
197*906Sgm89044 	/*
198*906Sgm89044 	 * Since the max RSA input size is 256 bytes (2048 bits), the firstx
199*906Sgm89044 	 * page (at least 4096 bytes) in the pre-mapped buffer is large enough.
200*906Sgm89044 	 * Therefore, we use this first page for RSA.
201*906Sgm89044 	 */
202*906Sgm89044 	reqp->dr_in_paddr = reqp->dr_ibuf_head.dc_buffer_paddr;
203*906Sgm89044 	reqp->dr_in_next = 0;
204*906Sgm89044 	reqp->dr_in_len = reqp->dr_pkt_length;
205*906Sgm89044 	reqp->dr_out_paddr = reqp->dr_obuf_head.dc_buffer_paddr;
206*906Sgm89044 	reqp->dr_out_next = 0;
207*906Sgm89044 	reqp->dr_out_len = reqp->dr_pkt_length;
208*906Sgm89044 
209*906Sgm89044 	/* schedule the work by doing a submit */
210*906Sgm89044 	rv = dca_start(dca, reqp, MCR2, 1);
211*906Sgm89044 
212*906Sgm89044 
213*906Sgm89044 errout:
214*906Sgm89044 	if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL)
215*906Sgm89044 		(void) dca_free_context(ctx);
216*906Sgm89044 
217*906Sgm89044 	return (rv);
218*906Sgm89044 }
219*906Sgm89044 
220*906Sgm89044 void
221*906Sgm89044 dca_rsadone(dca_request_t *reqp, int errno)
222*906Sgm89044 {
223*906Sgm89044 	if (errno == CRYPTO_SUCCESS) {
224*906Sgm89044 		int	outsz = reqp->dr_out->cd_length;
225*906Sgm89044 		caddr_t	daddr;
226*906Sgm89044 
227*906Sgm89044 		(void) ddi_dma_sync(reqp->dr_obuf_dmah, 0, reqp->dr_out_len,
228*906Sgm89044 		    DDI_DMA_SYNC_FORKERNEL);
229*906Sgm89044 		if (dca_check_dma_handle(reqp->dr_dca, reqp->dr_obuf_dmah,
230*906Sgm89044 		    DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
231*906Sgm89044 			reqp->destroy = TRUE;
232*906Sgm89044 			errno = CRYPTO_DEVICE_ERROR;
233*906Sgm89044 			goto errout;
234*906Sgm89044 		}
235*906Sgm89044 
236*906Sgm89044 		if (reqp->dr_ctx.mode == DCA_RSA_DEC ||
237*906Sgm89044 		    reqp->dr_ctx.mode == DCA_RSA_VRFY ||
238*906Sgm89044 		    reqp->dr_ctx.mode == DCA_RSA_VRFYR) {
239*906Sgm89044 			/*
240*906Sgm89044 			 * Needs to unpad appropriately for decrypt, verify,
241*906Sgm89044 			 * and verify_recover
242*906Sgm89044 			 */
243*906Sgm89044 			if (reqp->dr_ctx.ctx_cm_type ==
244*906Sgm89044 			    RSA_PKCS_MECH_INFO_TYPE) {
245*906Sgm89044 				errno = dca_pkcs1_unpadding(
246*906Sgm89044 				    reqp->dr_obuf_kaddr, &outsz,
247*906Sgm89044 				    reqp->dr_ctx.modlen, reqp->dr_ctx.mode);
248*906Sgm89044 
249*906Sgm89044 				/* check for bad data errors */
250*906Sgm89044 				if (errno != CRYPTO_SUCCESS &&
251*906Sgm89044 				    errno != CRYPTO_BUFFER_TOO_SMALL) {
252*906Sgm89044 					goto errout;
253*906Sgm89044 				}
254*906Sgm89044 				if (dca_bufdaddr(reqp->dr_out) == NULL) {
255*906Sgm89044 					errno = CRYPTO_BUFFER_TOO_SMALL;
256*906Sgm89044 				}
257*906Sgm89044 				if (errno == CRYPTO_BUFFER_TOO_SMALL) {
258*906Sgm89044 					reqp->dr_out->cd_length = outsz;
259*906Sgm89044 					goto errout;
260*906Sgm89044 				}
261*906Sgm89044 				/* Reset the output data length */
262*906Sgm89044 				reqp->dr_out->cd_length = outsz;
263*906Sgm89044 			} else if (reqp->dr_ctx.ctx_cm_type ==
264*906Sgm89044 			    RSA_X_509_MECH_INFO_TYPE) {
265*906Sgm89044 				if ((errno = dca_x509_unpadding(
266*906Sgm89044 				    reqp->dr_obuf_kaddr, outsz,
267*906Sgm89044 				    reqp->dr_pkt_length, reqp->dr_ctx.mode)) !=
268*906Sgm89044 				    CRYPTO_SUCCESS)
269*906Sgm89044 					goto errout;
270*906Sgm89044 			}
271*906Sgm89044 		}
272*906Sgm89044 
273*906Sgm89044 		if ((daddr = dca_bufdaddr(reqp->dr_out)) == NULL) {
274*906Sgm89044 			DBG(reqp->dr_dca, DINTR,
275*906Sgm89044 			    "dca_rsadone: reqp->dr_out is bad");
276*906Sgm89044 			errno = CRYPTO_ARGUMENTS_BAD;
277*906Sgm89044 			goto errout;
278*906Sgm89044 		}
279*906Sgm89044 		/*
280*906Sgm89044 		 * Note that there may be some number of null bytes
281*906Sgm89044 		 * at the end of the source (result), but we don't care
282*906Sgm89044 		 * about them -- they are place holders only and are
283*906Sgm89044 		 * truncated here.
284*906Sgm89044 		 */
285*906Sgm89044 		dca_reverse(reqp->dr_obuf_kaddr, daddr, outsz, outsz);
286*906Sgm89044 	}
287*906Sgm89044 errout:
288*906Sgm89044 	ASSERT(reqp->dr_kcf_req != NULL);
289*906Sgm89044 
290*906Sgm89044 	/* notify framework that request is completed */
291*906Sgm89044 	crypto_op_notification(reqp->dr_kcf_req, errno);
292*906Sgm89044 	DBG(reqp->dr_dca, DINTR,
293*906Sgm89044 	    "dca_rsadone: returning 0x%x to the kef via crypto_op_notification",
294*906Sgm89044 	    errno);
295*906Sgm89044 
296*906Sgm89044 	/*
297*906Sgm89044 	 * For non-atomic operations, reqp will be freed in the kCF
298*906Sgm89044 	 * callback function since it may be needed again if
299*906Sgm89044 	 * CRYPTO_BUFFER_TOO_SMALL is returned to kCF
300*906Sgm89044 	 */
301*906Sgm89044 	if (reqp->dr_ctx.atomic) {
302*906Sgm89044 		crypto_ctx_t ctx;
303*906Sgm89044 		ctx.cc_provider_private = reqp;
304*906Sgm89044 		dca_rsactxfree(&ctx);
305*906Sgm89044 	}
306*906Sgm89044 }
307*906Sgm89044 
308*906Sgm89044 void
309*906Sgm89044 dca_rsaverifydone(dca_request_t *reqp, int errno)
310*906Sgm89044 {
311*906Sgm89044 	if (errno == CRYPTO_SUCCESS) {
312*906Sgm89044 		char	scratch[RSA_MAX_KEY_LEN];
313*906Sgm89044 		int	outsz = reqp->dr_out->cd_length;
314*906Sgm89044 		caddr_t	daddr;
315*906Sgm89044 
316*906Sgm89044 		/*
317*906Sgm89044 		 * ASSUMPTION: the signature length was already
318*906Sgm89044 		 * checked on the way in, and it is a valid length.
319*906Sgm89044 		 */
320*906Sgm89044 		(void) ddi_dma_sync(reqp->dr_obuf_dmah, 0, outsz,
321*906Sgm89044 		    DDI_DMA_SYNC_FORKERNEL);
322*906Sgm89044 		if (dca_check_dma_handle(reqp->dr_dca, reqp->dr_obuf_dmah,
323*906Sgm89044 		    DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
324*906Sgm89044 			reqp->destroy = TRUE;
325*906Sgm89044 			errno = CRYPTO_DEVICE_ERROR;
326*906Sgm89044 			goto errout;
327*906Sgm89044 		}
328*906Sgm89044 
329*906Sgm89044 		if (reqp->dr_ctx.mode == DCA_RSA_DEC ||
330*906Sgm89044 		    reqp->dr_ctx.mode == DCA_RSA_VRFY ||
331*906Sgm89044 		    reqp->dr_ctx.mode == DCA_RSA_VRFYR) {
332*906Sgm89044 			/*
333*906Sgm89044 			 * Needs to unpad appropriately for decrypt, verify,
334*906Sgm89044 			 * and verify_recover
335*906Sgm89044 			 */
336*906Sgm89044 			if (reqp->dr_ctx.ctx_cm_type ==
337*906Sgm89044 			    RSA_PKCS_MECH_INFO_TYPE) {
338*906Sgm89044 				errno = dca_pkcs1_unpadding(
339*906Sgm89044 				    reqp->dr_obuf_kaddr, &outsz,
340*906Sgm89044 				    reqp->dr_ctx.modlen, reqp->dr_ctx.mode);
341*906Sgm89044 
342*906Sgm89044 				/* check for bad data errors */
343*906Sgm89044 				if (errno != CRYPTO_SUCCESS &&
344*906Sgm89044 				    errno != CRYPTO_BUFFER_TOO_SMALL) {
345*906Sgm89044 					goto errout;
346*906Sgm89044 				}
347*906Sgm89044 				if (dca_bufdaddr(reqp->dr_out) == NULL) {
348*906Sgm89044 					errno = CRYPTO_BUFFER_TOO_SMALL;
349*906Sgm89044 				}
350*906Sgm89044 				if (errno == CRYPTO_BUFFER_TOO_SMALL) {
351*906Sgm89044 					reqp->dr_out->cd_length = outsz;
352*906Sgm89044 					goto errout;
353*906Sgm89044 				}
354*906Sgm89044 				/* Reset the output data length */
355*906Sgm89044 				reqp->dr_out->cd_length = outsz;
356*906Sgm89044 			} else if (reqp->dr_ctx.ctx_cm_type ==
357*906Sgm89044 			    RSA_X_509_MECH_INFO_TYPE) {
358*906Sgm89044 				if ((errno = dca_x509_unpadding(
359*906Sgm89044 				    reqp->dr_obuf_kaddr, outsz,
360*906Sgm89044 				    reqp->dr_pkt_length, reqp->dr_ctx.mode)) !=
361*906Sgm89044 				    CRYPTO_SUCCESS)
362*906Sgm89044 					goto errout;
363*906Sgm89044 			}
364*906Sgm89044 		}
365*906Sgm89044 
366*906Sgm89044 		dca_reverse(reqp->dr_obuf_kaddr, scratch, outsz, outsz);
367*906Sgm89044 
368*906Sgm89044 		if ((daddr = dca_bufdaddr(reqp->dr_out)) == NULL) {
369*906Sgm89044 			errno = CRYPTO_ARGUMENTS_BAD;
370*906Sgm89044 			goto errout;
371*906Sgm89044 		}
372*906Sgm89044 		if (dca_numcmp(daddr, reqp->dr_out->cd_length, scratch,
373*906Sgm89044 		    outsz) != 0) {
374*906Sgm89044 			/* VERIFY FAILED */
375*906Sgm89044 			errno = CRYPTO_SIGNATURE_INVALID;
376*906Sgm89044 		}
377*906Sgm89044 	}
378*906Sgm89044 errout:
379*906Sgm89044 	ASSERT(reqp->dr_kcf_req != NULL);
380*906Sgm89044 
381*906Sgm89044 	/* notify framework that request is completed */
382*906Sgm89044 	crypto_op_notification(reqp->dr_kcf_req, errno);
383*906Sgm89044 	DBG(reqp->dr_dca, DINTR,
384*906Sgm89044 	    "dca_rsaverifydone: rtn 0x%x to the kef via crypto_op_notification",
385*906Sgm89044 	    errno);
386*906Sgm89044 
387*906Sgm89044 	/*
388*906Sgm89044 	 * For non-atomic operations, reqp will be freed in the kCF
389*906Sgm89044 	 * callback function since it may be needed again if
390*906Sgm89044 	 * CRYPTO_BUFFER_TOO_SMALL is returned to kCF
391*906Sgm89044 	 */
392*906Sgm89044 	if (reqp->dr_ctx.atomic) {
393*906Sgm89044 		crypto_ctx_t ctx;
394*906Sgm89044 		ctx.cc_provider_private = reqp;
395*906Sgm89044 		dca_rsactxfree(&ctx);
396*906Sgm89044 	}
397*906Sgm89044 }
398*906Sgm89044 
399*906Sgm89044 /*
400*906Sgm89044  * Setup either a public or a private RSA key for subsequent uses
401*906Sgm89044  */
402*906Sgm89044 int
403*906Sgm89044 dca_rsainit(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
404*906Sgm89044     crypto_key_t *key, int kmflag)
405*906Sgm89044 {
406*906Sgm89044 	crypto_object_attribute_t	*attr;
407*906Sgm89044 	unsigned			expname = 0;
408*906Sgm89044 	void				*attrdata;
409*906Sgm89044 	int rv;
410*906Sgm89044 
411*906Sgm89044 	uchar_t			*exp;
412*906Sgm89044 	uchar_t			*p;
413*906Sgm89044 	uchar_t			*q;
414*906Sgm89044 	uchar_t			*dp;
415*906Sgm89044 	uchar_t			*dq;
416*906Sgm89044 	uchar_t			*pinv;
417*906Sgm89044 
418*906Sgm89044 	unsigned		explen = 0;
419*906Sgm89044 	unsigned		plen = 0;
420*906Sgm89044 	unsigned		qlen = 0;
421*906Sgm89044 	unsigned		dplen = 0;
422*906Sgm89044 	unsigned		dqlen = 0;
423*906Sgm89044 	unsigned		pinvlen = 0;
424*906Sgm89044 
425*906Sgm89044 	unsigned		modbits, expbits, pbits, qbits;
426*906Sgm89044 	unsigned		modfix, expfix, pqfix = 0;
427*906Sgm89044 	uint16_t		ctxlen;
428*906Sgm89044 	caddr_t			kaddr;
429*906Sgm89044 	dca_request_t		*reqp = NULL;
430*906Sgm89044 	dca_t			*dca = (dca_t *)ctx->cc_provider;
431*906Sgm89044 
432*906Sgm89044 	DBG(NULL, DENTRY, "dca_rsainit: start");
433*906Sgm89044 
434*906Sgm89044 	if ((reqp = dca_getreq(dca, MCR2, 1)) == NULL) {
435*906Sgm89044 		DBG(NULL, DWARN,
436*906Sgm89044 		    "dca_rsainit: unable to allocate request for RSA");
437*906Sgm89044 		rv = CRYPTO_HOST_MEMORY;
438*906Sgm89044 		goto errout;
439*906Sgm89044 	}
440*906Sgm89044 
441*906Sgm89044 	reqp->dr_ctx.ctx_cm_type = mechanism->cm_type;
442*906Sgm89044 	ctx->cc_provider_private = reqp;
443*906Sgm89044 
444*906Sgm89044 	/*
445*906Sgm89044 	 * Key type can be either RAW, or REFERENCE, or ATTR_LIST (VALUE).
446*906Sgm89044 	 * Only ATTR_LIST is supported on Deimos for RSA.
447*906Sgm89044 	 */
448*906Sgm89044 	if ((attr = dca_get_key_attr(key)) == NULL) {
449*906Sgm89044 		DBG(NULL, DWARN, "dca_rsainit: key attributes missing");
450*906Sgm89044 		rv = CRYPTO_KEY_TYPE_INCONSISTENT;
451*906Sgm89044 		goto errout;
452*906Sgm89044 	}
453*906Sgm89044 
454*906Sgm89044 	if (dca_find_attribute(attr, key->ck_count, CKA_PUBLIC_EXPONENT))
455*906Sgm89044 		expname = CKA_PUBLIC_EXPONENT;
456*906Sgm89044 
457*906Sgm89044 	/*
458*906Sgm89044 	 * RSA public key has only public exponent. RSA private key must have
459*906Sgm89044 	 * private exponent. However, it may also have public exponent.
460*906Sgm89044 	 * Thus, the existance of a private exponent indicates a private key.
461*906Sgm89044 	 */
462*906Sgm89044 	if (dca_find_attribute(attr, key->ck_count, CKA_PRIVATE_EXPONENT))
463*906Sgm89044 		expname = CKA_PRIVATE_EXPONENT;
464*906Sgm89044 
465*906Sgm89044 	if (!expname) {
466*906Sgm89044 		DBG(NULL, DWARN, "dca_rsainit: no exponent in key");
467*906Sgm89044 		rv = CRYPTO_ARGUMENTS_BAD;
468*906Sgm89044 		goto errout;
469*906Sgm89044 	}
470*906Sgm89044 
471*906Sgm89044 	/* Modulus */
472*906Sgm89044 	if ((rv = dca_attr_lookup_uint8_array(attr, key->ck_count, CKA_MODULUS,
473*906Sgm89044 	    &attrdata, &(reqp->dr_ctx.modlen))) != CRYPTO_SUCCESS) {
474*906Sgm89044 		DBG(NULL, DWARN, "dca_rsainit: failed to retrieve modulus");
475*906Sgm89044 		goto errout;
476*906Sgm89044 	}
477*906Sgm89044 	if ((reqp->dr_ctx.modlen == 0) ||
478*906Sgm89044 	    (reqp->dr_ctx.modlen > RSA_MAX_KEY_LEN)) {
479*906Sgm89044 		DBG(NULL, DWARN, "dca_rsainit: bad modulus size");
480*906Sgm89044 		rv = CRYPTO_ARGUMENTS_BAD;
481*906Sgm89044 		goto errout;
482*906Sgm89044 	}
483*906Sgm89044 	if ((reqp->dr_ctx.mod = kmem_alloc(reqp->dr_ctx.modlen, kmflag)) ==
484*906Sgm89044 	    NULL) {
485*906Sgm89044 		rv = CRYPTO_HOST_MEMORY;
486*906Sgm89044 		goto errout;
487*906Sgm89044 	}
488*906Sgm89044 	bcopy(attrdata, reqp->dr_ctx.mod, reqp->dr_ctx.modlen);
489*906Sgm89044 
490*906Sgm89044 	/* Exponent */
491*906Sgm89044 	if ((rv = dca_attr_lookup_uint8_array(attr, key->ck_count, expname,
492*906Sgm89044 	    (void **) &exp, &explen)) != CRYPTO_SUCCESS) {
493*906Sgm89044 		DBG(NULL, DWARN, "dca_rsainit: failed to retrieve exponent");
494*906Sgm89044 		goto errout;
495*906Sgm89044 	}
496*906Sgm89044 	if ((explen == 0) || (explen > RSA_MAX_KEY_LEN)) {
497*906Sgm89044 		DBG(NULL, DWARN, "dca_rsainit: bad exponent size");
498*906Sgm89044 		rv = CRYPTO_ARGUMENTS_BAD;
499*906Sgm89044 		goto errout;
500*906Sgm89044 	}
501*906Sgm89044 
502*906Sgm89044 	/* Lookup private attributes */
503*906Sgm89044 	if (expname == CKA_PRIVATE_EXPONENT) {
504*906Sgm89044 		/* Prime 1 */
505*906Sgm89044 		(void) dca_attr_lookup_uint8_array(attr, key->ck_count,
506*906Sgm89044 		    CKA_PRIME_1, (void **)&q, &qlen);
507*906Sgm89044 
508*906Sgm89044 		/* Prime 2 */
509*906Sgm89044 		(void) dca_attr_lookup_uint8_array(attr, key->ck_count,
510*906Sgm89044 		    CKA_PRIME_2, (void **)&p, &plen);
511*906Sgm89044 
512*906Sgm89044 		/* Exponent 1 */
513*906Sgm89044 		(void) dca_attr_lookup_uint8_array(attr, key->ck_count,
514*906Sgm89044 		    CKA_EXPONENT_1, (void **)&dq, &dqlen);
515*906Sgm89044 
516*906Sgm89044 		/* Exponent 2 */
517*906Sgm89044 		(void) dca_attr_lookup_uint8_array(attr, key->ck_count,
518*906Sgm89044 		    CKA_EXPONENT_2, (void **)&dp, &dplen);
519*906Sgm89044 
520*906Sgm89044 		/* Coefficient */
521*906Sgm89044 		(void) dca_attr_lookup_uint8_array(attr, key->ck_count,
522*906Sgm89044 		    CKA_COEFFICIENT, (void **)&pinv, &pinvlen);
523*906Sgm89044 	}
524*906Sgm89044 
525*906Sgm89044 	modbits = dca_bitlen(reqp->dr_ctx.mod, reqp->dr_ctx.modlen);
526*906Sgm89044 	expbits = dca_bitlen(exp, explen);
527*906Sgm89044 
528*906Sgm89044 	if ((modfix = dca_padfull(modbits)) == 0) {
529*906Sgm89044 		DBG(NULL, DWARN, "dca_rsainit: modulus too long");
530*906Sgm89044 		rv = CRYPTO_KEY_SIZE_RANGE;
531*906Sgm89044 		goto errout;
532*906Sgm89044 	}
533*906Sgm89044 	expfix =  ROUNDUP(explen, sizeof (uint32_t));
534*906Sgm89044 
535*906Sgm89044 	if (plen && qlen && dplen && dqlen && pinvlen) {
536*906Sgm89044 		unsigned pfix, qfix;
537*906Sgm89044 		qbits = dca_bitlen(q, qlen);
538*906Sgm89044 		pbits = dca_bitlen(p, plen);
539*906Sgm89044 		qfix = dca_padhalf(qbits);
540*906Sgm89044 		pfix = dca_padhalf(pbits);
541*906Sgm89044 		if (pfix & qfix)
542*906Sgm89044 			pqfix = max(pfix, qfix);
543*906Sgm89044 	}
544*906Sgm89044 
545*906Sgm89044 	if (pqfix) {
546*906Sgm89044 		reqp->dr_job_stat = DS_RSAPRIVATE;
547*906Sgm89044 		reqp->dr_pkt_length = 2 * pqfix;
548*906Sgm89044 	} else {
549*906Sgm89044 		reqp->dr_job_stat = DS_RSAPUBLIC;
550*906Sgm89044 		reqp->dr_pkt_length = modfix;
551*906Sgm89044 	}
552*906Sgm89044 
553*906Sgm89044 	if (pqfix) {
554*906Sgm89044 		/*
555*906Sgm89044 		 * NOTE: chip's notion of p vs. q is reversed from
556*906Sgm89044 		 * PKCS#11.  We use the chip's notion in our variable
557*906Sgm89044 		 * naming.
558*906Sgm89044 		 */
559*906Sgm89044 		ctxlen = 8 + pqfix * 5;
560*906Sgm89044 
561*906Sgm89044 		/* write out the context structure */
562*906Sgm89044 		PUTCTX16(reqp, CTX_CMD, CMD_RSAPRIVATE);
563*906Sgm89044 		PUTCTX16(reqp, CTX_LENGTH, ctxlen);
564*906Sgm89044 		/* exponent and modulus length in bits!!! */
565*906Sgm89044 		PUTCTX16(reqp, CTX_RSAQLEN, qbits);
566*906Sgm89044 		PUTCTX16(reqp, CTX_RSAPLEN, pbits);
567*906Sgm89044 
568*906Sgm89044 		kaddr = reqp->dr_ctx_kaddr + CTX_RSABIGNUMS;
569*906Sgm89044 
570*906Sgm89044 		/* store the bignums */
571*906Sgm89044 		dca_reverse(p, kaddr, plen, pqfix);
572*906Sgm89044 		kaddr += pqfix;
573*906Sgm89044 
574*906Sgm89044 		dca_reverse(q, kaddr, qlen, pqfix);
575*906Sgm89044 		kaddr += pqfix;
576*906Sgm89044 
577*906Sgm89044 		dca_reverse(dp, kaddr, dplen, pqfix);
578*906Sgm89044 		kaddr += pqfix;
579*906Sgm89044 
580*906Sgm89044 		dca_reverse(dq, kaddr, dqlen, pqfix);
581*906Sgm89044 		kaddr += pqfix;
582*906Sgm89044 
583*906Sgm89044 		dca_reverse(pinv, kaddr, pinvlen, pqfix);
584*906Sgm89044 		kaddr += pqfix;
585*906Sgm89044 	} else {
586*906Sgm89044 		ctxlen = 8 + modfix + expfix;
587*906Sgm89044 		/* write out the context structure */
588*906Sgm89044 		PUTCTX16(reqp, CTX_CMD, CMD_RSAPUBLIC);
589*906Sgm89044 		PUTCTX16(reqp, CTX_LENGTH, (uint16_t)ctxlen);
590*906Sgm89044 		/* exponent and modulus length in bits!!! */
591*906Sgm89044 		PUTCTX16(reqp, CTX_RSAEXPLEN, expbits);
592*906Sgm89044 		PUTCTX16(reqp, CTX_RSAMODLEN, modbits);
593*906Sgm89044 
594*906Sgm89044 		kaddr = reqp->dr_ctx_kaddr + CTX_RSABIGNUMS;
595*906Sgm89044 
596*906Sgm89044 		/* store the bignums */
597*906Sgm89044 		dca_reverse(reqp->dr_ctx.mod, kaddr, reqp->dr_ctx.modlen,
598*906Sgm89044 		    modfix);
599*906Sgm89044 		kaddr += modfix;
600*906Sgm89044 
601*906Sgm89044 		dca_reverse(exp, kaddr, explen, expfix);
602*906Sgm89044 		kaddr += expfix;
603*906Sgm89044 	}
604*906Sgm89044 
605*906Sgm89044 	reqp->dr_ctx.pqfix = pqfix;
606*906Sgm89044 
607*906Sgm89044 errout:
608*906Sgm89044 	if (rv != CRYPTO_SUCCESS)
609*906Sgm89044 		dca_rsactxfree(ctx);
610*906Sgm89044 
611*906Sgm89044 	return (rv);
612*906Sgm89044 }
613*906Sgm89044 
614*906Sgm89044 void
615*906Sgm89044 dca_rsactxfree(void *arg)
616*906Sgm89044 {
617*906Sgm89044 	crypto_ctx_t	*ctx = (crypto_ctx_t *)arg;
618*906Sgm89044 	dca_request_t	*reqp = ctx->cc_provider_private;
619*906Sgm89044 
620*906Sgm89044 	if (reqp == NULL)
621*906Sgm89044 		return;
622*906Sgm89044 
623*906Sgm89044 	if (reqp->dr_ctx.mod)
624*906Sgm89044 		kmem_free(reqp->dr_ctx.mod, reqp->dr_ctx.modlen);
625*906Sgm89044 
626*906Sgm89044 	reqp->dr_ctx.mode = 0;
627*906Sgm89044 	reqp->dr_ctx.ctx_cm_type = 0;
628*906Sgm89044 	reqp->dr_ctx.mod = NULL;
629*906Sgm89044 	reqp->dr_ctx.modlen = 0;
630*906Sgm89044 	reqp->dr_ctx.pqfix = 0;
631*906Sgm89044 	reqp->dr_ctx.atomic = 0;
632*906Sgm89044 
633*906Sgm89044 	if (reqp->destroy)
634*906Sgm89044 		dca_destroyreq(reqp);
635*906Sgm89044 	else
636*906Sgm89044 		dca_freereq(reqp);
637*906Sgm89044 
638*906Sgm89044 	ctx->cc_provider_private = NULL;
639*906Sgm89044 }
640*906Sgm89044 
641*906Sgm89044 int
642*906Sgm89044 dca_rsaatomic(crypto_provider_handle_t provider,
643*906Sgm89044     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
644*906Sgm89044     crypto_key_t *key, crypto_data_t *input, crypto_data_t *output,
645*906Sgm89044     int kmflag, crypto_req_handle_t req, int mode)
646*906Sgm89044 {
647*906Sgm89044 	crypto_ctx_t	ctx;	/* on the stack */
648*906Sgm89044 	int		rv;
649*906Sgm89044 
650*906Sgm89044 	ctx.cc_provider = provider;
651*906Sgm89044 	ctx.cc_session = session_id;
652*906Sgm89044 
653*906Sgm89044 	rv = dca_rsainit(&ctx, mechanism, key, kmflag);
654*906Sgm89044 	if (rv != CRYPTO_SUCCESS) {
655*906Sgm89044 		DBG(NULL, DWARN, "dca_rsaatomic: dca_rsainit() failed");
656*906Sgm89044 		/* The content of ctx should have been freed already */
657*906Sgm89044 		return (rv);
658*906Sgm89044 	}
659*906Sgm89044 
660*906Sgm89044 	/*
661*906Sgm89044 	 * Set the atomic flag so that the hardware callback function
662*906Sgm89044 	 * will free the context.
663*906Sgm89044 	 */
664*906Sgm89044 	((dca_request_t *)ctx.cc_provider_private)->dr_ctx.atomic = 1;
665*906Sgm89044 
666*906Sgm89044 	rv = dca_rsastart(&ctx, input, output, req, mode);
667*906Sgm89044 
668*906Sgm89044 	/*
669*906Sgm89044 	 * The context will be freed in the hardware callback function if it
670*906Sgm89044 	 * is queued
671*906Sgm89044 	 */
672*906Sgm89044 	if (rv != CRYPTO_QUEUED)
673*906Sgm89044 		dca_rsactxfree(&ctx);
674*906Sgm89044 
675*906Sgm89044 	return (rv);
676*906Sgm89044 }
677*906Sgm89044 
678*906Sgm89044 
679*906Sgm89044 /*
680*906Sgm89044  * For RSA_PKCS padding and unpadding:
681*906Sgm89044  * 1. The minimum padding is 11 bytes.
682*906Sgm89044  * 2. The first and the last bytes must 0.
683*906Sgm89044  * 3. The second byte is 1 for private and 2 for public keys.
684*906Sgm89044  * 4. Pad with 0xff for private and non-zero random for public keys.
685*906Sgm89044  */
686*906Sgm89044 static int
687*906Sgm89044 dca_pkcs1_padding(dca_t *dca, caddr_t buf, int flen, int tlen, int private)
688*906Sgm89044 {
689*906Sgm89044 	int i;
690*906Sgm89044 
691*906Sgm89044 	DBG(NULL, DENTRY,
692*906Sgm89044 	    "dca_pkcs1_padding: tlen: %d, flen: %d: private: %d\n",
693*906Sgm89044 	    tlen, flen, private);
694*906Sgm89044 
695*906Sgm89044 	if (flen > tlen - 11)
696*906Sgm89044 		return (CRYPTO_DATA_LEN_RANGE);
697*906Sgm89044 
698*906Sgm89044 	if (private) {
699*906Sgm89044 		/* Padding for private encrypt */
700*906Sgm89044 		buf[flen] = '\0';
701*906Sgm89044 		for (i = flen + 1; i < tlen - 2; i++) {
702*906Sgm89044 			buf[i] = (unsigned char) 0xff;
703*906Sgm89044 		}
704*906Sgm89044 		buf[tlen - 2] = 1;
705*906Sgm89044 		buf[tlen - 1] = 0;
706*906Sgm89044 	} else {
707*906Sgm89044 		/* Padding for public encrypt */
708*906Sgm89044 		buf[flen] = '\0';
709*906Sgm89044 
710*906Sgm89044 		if (dca_random_buffer(dca, &buf[flen+1], tlen - flen - 3) !=
711*906Sgm89044 		    CRYPTO_SUCCESS)
712*906Sgm89044 			return (CRYPTO_RANDOM_NO_RNG);
713*906Sgm89044 
714*906Sgm89044 		buf[tlen - 2] = 2;
715*906Sgm89044 		buf[tlen - 1] = 0;
716*906Sgm89044 	}
717*906Sgm89044 
718*906Sgm89044 	return (CRYPTO_QUEUED);
719*906Sgm89044 }
720*906Sgm89044 
721*906Sgm89044 static int
722*906Sgm89044 dca_pkcs1_unpadding(char *buf, int *tlen, int flen, int mode)
723*906Sgm89044 {
724*906Sgm89044 	int i;
725*906Sgm89044 	const unsigned char *p;
726*906Sgm89044 	unsigned char type;
727*906Sgm89044 
728*906Sgm89044 	DBG(NULL, DENTRY, "dca_pkcs1_unpadding: tlen: %d, flen: %d\n",
729*906Sgm89044 	    *tlen, flen);
730*906Sgm89044 
731*906Sgm89044 	p = (unsigned char *) buf + (flen-1);
732*906Sgm89044 	if (*(p--) != 0)
733*906Sgm89044 		return decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
734*906Sgm89044 		    CRYPTO_SIGNATURE_INVALID, CRYPTO_DATA_INVALID);
735*906Sgm89044 
736*906Sgm89044 	/* It is ok if the data length is 0 after removing the padding */
737*906Sgm89044 	type = *(p--);
738*906Sgm89044 	if (type == 01) {
739*906Sgm89044 		for (i = flen - 3; i >= 0; i--) {
740*906Sgm89044 			if (*p != 0xff) {
741*906Sgm89044 				if (*p == '\0') {
742*906Sgm89044 					p--;
743*906Sgm89044 					break;
744*906Sgm89044 				} else {
745*906Sgm89044 					return decrypt_error_code(mode,
746*906Sgm89044 					    CRYPTO_ENCRYPTED_DATA_INVALID,
747*906Sgm89044 					    CRYPTO_SIGNATURE_INVALID,
748*906Sgm89044 					    CRYPTO_DATA_INVALID);
749*906Sgm89044 				}
750*906Sgm89044 			}
751*906Sgm89044 			p--;
752*906Sgm89044 		}
753*906Sgm89044 	} else if (type == 02) {
754*906Sgm89044 		for (i = flen - 3; i >= 0; i--) {
755*906Sgm89044 			if (*p == '\0') {
756*906Sgm89044 				p--;
757*906Sgm89044 				break;
758*906Sgm89044 			}
759*906Sgm89044 			p--;
760*906Sgm89044 		}
761*906Sgm89044 	} else {
762*906Sgm89044 		return decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
763*906Sgm89044 		    CRYPTO_SIGNATURE_INVALID, CRYPTO_DATA_INVALID);
764*906Sgm89044 	}
765*906Sgm89044 
766*906Sgm89044 	/* i < 0 means did not find the end of the padding */
767*906Sgm89044 	if (i < 0)
768*906Sgm89044 		return decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
769*906Sgm89044 		    CRYPTO_SIGNATURE_INVALID, CRYPTO_DATA_INVALID);
770*906Sgm89044 
771*906Sgm89044 	if (i > *tlen) {
772*906Sgm89044 		*tlen = i;
773*906Sgm89044 		return (CRYPTO_BUFFER_TOO_SMALL);
774*906Sgm89044 	}
775*906Sgm89044 
776*906Sgm89044 	if (flen - i < 11)
777*906Sgm89044 		return decrypt_error_code(mode,
778*906Sgm89044 		    CRYPTO_ENCRYPTED_DATA_LEN_RANGE,
779*906Sgm89044 		    CRYPTO_SIGNATURE_LEN_RANGE, CRYPTO_DATA_LEN_RANGE);
780*906Sgm89044 
781*906Sgm89044 	/* Return the unpadded length to the caller */
782*906Sgm89044 	*tlen = i;
783*906Sgm89044 
784*906Sgm89044 	return (CRYPTO_SUCCESS);
785*906Sgm89044 }
786*906Sgm89044 
787*906Sgm89044 /*
788*906Sgm89044  * For RSA_X_509 padding and unpadding, pad all 0s before actual data.
789*906Sgm89044  * Note that the data will be in reverse order.
790*906Sgm89044  */
791*906Sgm89044 static int
792*906Sgm89044 dca_x509_padding(caddr_t buf, int flen, int tlen)
793*906Sgm89044 {
794*906Sgm89044 	DBG(NULL, DENTRY, "dca_x509_padding: tlen: %d, flen: %d\n",
795*906Sgm89044 	    tlen, flen);
796*906Sgm89044 
797*906Sgm89044 	bzero(buf+tlen, tlen - flen);
798*906Sgm89044 
799*906Sgm89044 	return (CRYPTO_QUEUED);
800*906Sgm89044 }
801*906Sgm89044 
802*906Sgm89044 /* ARGSUSED */
803*906Sgm89044 static int
804*906Sgm89044 dca_x509_unpadding(char *buf, int tlen, int flen, int mode)
805*906Sgm89044 {
806*906Sgm89044 	int i;
807*906Sgm89044 	const unsigned char *p;
808*906Sgm89044 
809*906Sgm89044 	DBG(NULL, DENTRY, "dca_x509_unpadding: tlen: %d, flen: %d\n",
810*906Sgm89044 	    tlen, flen);
811*906Sgm89044 
812*906Sgm89044 	p = (unsigned char *) buf + flen;
813*906Sgm89044 	for (i = tlen; i < flen; i++) {
814*906Sgm89044 		if (*(--p) != 0)
815*906Sgm89044 			return (CRYPTO_SIGNATURE_INVALID);
816*906Sgm89044 	}
817*906Sgm89044 
818*906Sgm89044 	return (CRYPTO_SUCCESS);
819*906Sgm89044 }
820*906Sgm89044 
821*906Sgm89044 static int decrypt_error_code(int mode, int decrypt, int verify, int def)
822*906Sgm89044 {
823*906Sgm89044 	switch (mode) {
824*906Sgm89044 	case DCA_RSA_DEC:
825*906Sgm89044 		return (decrypt);
826*906Sgm89044 	case DCA_RSA_VRFY:
827*906Sgm89044 	case DCA_RSA_VRFYR:
828*906Sgm89044 		return (verify);
829*906Sgm89044 	default:
830*906Sgm89044 		return (def);
831*906Sgm89044 	}
832*906Sgm89044 }
833