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