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