88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CDDL HEADER START
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The contents of this file are subject to the terms of the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Common Development and Distribution License (the "License").
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * You may not use this file except in compliance with the License.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * See the License for the specific language governing permissions
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * and limitations under the License.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * When distributing Covered Code, include this CDDL HEADER in each
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If applicable, add the following below this CDDL HEADER, with the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * fields enclosed by brackets "[]" replaced with your own identifying
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * information: Portions Copyright [yyyy] [name of copyright owner]
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CDDL HEADER END
d8dd99136aadc95161b4031565b92214f8bbc8c8gm * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Use is subject to license terms.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#pragma ident "%Z%%M% %I% %E% SMI"
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Deimos - cryptographic acceleration based upon Broadcom 582x.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/* Exported function prototypes */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_rsastart(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_rsainit(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, int);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmvoid dca_rsactxfree(void *);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_rsaatomic(crypto_provider_handle_t, crypto_session_id_t,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/* Local function prototypes */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int dca_pkcs1_padding(dca_t *dca, caddr_t buf, int flen, int tlen,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int dca_pkcs1_unpadding(char *buf, int *tlen, int flen, int mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int dca_x509_padding(caddr_t buf, int flen, int tlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int dca_x509_unpadding(char *buf, int tlen, int flen, int mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int decrypt_error_code(int mode, int decrypt, int verify, int def);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_rsastart(crypto_ctx_t *ctx, crypto_data_t *in, crypto_data_t *out,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* We don't support non-contiguous buffers for RSA */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Extracting the key attributes is now done in dca_rsainit(). */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Return length needed to store the output.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For sign, sign-recover, and encrypt, the output buffer
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * should not be smaller than modlen since PKCS or X_509
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * padding will be applied
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsastart: output buffer too short (%d < %d)",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* The input length should not be bigger than the modulus */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_LEN_RANGE,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For decryption, verify, and verifyRecover, the input length should
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * not be less than the modulus
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_LEN_RANGE,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For decryption and verifyRecover, the output buffer should not
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * be less than the modulus
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (out->cd_length < reqp->dr_ctx.modlen && (mode == DCA_RSA_DEC ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* For decrypt and verify, the input should not be less than output */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsastart: input larger (numerically) than modulus!");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(daddr, reqp->dr_ibuf_kaddr, len, reqp->dr_pkt_length);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Needs to pad appropriately for encrypt, sign, and
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * sign_recover
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.ctx_cm_type == RSA_PKCS_MECH_INFO_TYPE) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Since the max RSA input size is 256 bytes (2048 bits), the firstx
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * page (at least 4096 bytes) in the pre-mapped buffer is large enough.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Therefore, we use this first page for RSA.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* schedule the work by doing a submit */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) ddi_dma_sync(reqp->dr_obuf_dmah, 0, reqp->dr_out_len,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_check_dma_handle(reqp->dr_dca, reqp->dr_obuf_dmah,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Needs to unpad appropriately for decrypt, verify,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * and verify_recover
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* check for bad data errors */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Reset the output data length */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsadone: reqp->dr_out is bad");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Note that there may be some number of null bytes
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * at the end of the source (result), but we don't care
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * about them -- they are place holders only and are
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * truncated here.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* notify framework that request is completed */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsadone: returning 0x%x to the kef via crypto_op_notification",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For non-atomic operations, reqp will be freed in the kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * callback function since it may be needed again if
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CRYPTO_BUFFER_TOO_SMALL is returned to kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * ASSUMPTION: the signature length was already
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * checked on the way in, and it is a valid length.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_check_dma_handle(reqp->dr_dca, reqp->dr_obuf_dmah,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Needs to unpad appropriately for decrypt, verify,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * and verify_recover
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* check for bad data errors */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Reset the output data length */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* VERIFY FAILED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* notify framework that request is completed */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsaverifydone: rtn 0x%x to the kef via crypto_op_notification",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For non-atomic operations, reqp will be freed in the kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * callback function since it may be needed again if
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CRYPTO_BUFFER_TOO_SMALL is returned to kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Setup either a public or a private RSA key for subsequent uses
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_rsainit(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_rsainit: unable to allocate request for RSA");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Key type can be either RAW, or REFERENCE, or ATTR_LIST (VALUE).
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Only ATTR_LIST is supported on Deimos for RSA.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_find_attribute(attr, key->ck_count, CKA_PUBLIC_EXPONENT))
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * RSA public key has only public exponent. RSA private key must have
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * private exponent. However, it may also have public exponent.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Thus, the existance of a private exponent indicates a private key.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_find_attribute(attr, key->ck_count, CKA_PRIVATE_EXPONENT))
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Modulus */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_attr_lookup_uint8_array(attr, key->ck_count, CKA_MODULUS,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_rsainit: failed to retrieve modulus");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((reqp->dr_ctx.mod = kmem_alloc(reqp->dr_ctx.modlen, kmflag)) ==
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Exponent */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_attr_lookup_uint8_array(attr, key->ck_count, expname,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_rsainit: failed to retrieve exponent");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Lookup private attributes */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Prime 1 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Prime 2 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Exponent 1 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Exponent 2 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Coefficient */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm modbits = dca_bitlen(reqp->dr_ctx.mod, reqp->dr_ctx.modlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * NOTE: chip's notion of p vs. q is reversed from
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * PKCS#11. We use the chip's notion in our variable
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* write out the context structure */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* exponent and modulus length in bits!!! */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* store the bignums */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* write out the context structure */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* exponent and modulus length in bits!!! */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* store the bignums */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(reqp->dr_ctx.mod, kaddr, reqp->dr_ctx.modlen,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_key_t *key, crypto_data_t *input, crypto_data_t *output,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* The content of ctx should have been freed already */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Set the atomic flag so that the hardware callback function
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * will free the context.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ((dca_request_t *)ctx.cc_provider_private)->dr_ctx.atomic = 1;
d8dd99136aadc95161b4031565b92214f8bbc8c8gm /* check for inplace ops */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The context will be freed in the hardware callback function if it
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * is queued
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For RSA_PKCS padding and unpadding:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 1. The minimum padding is 11 bytes.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 2. The first and the last bytes must 0.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 3. The second byte is 1 for private and 2 for public keys.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 4. Pad with 0xff for private and non-zero random for public keys.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_pkcs1_padding(dca_t *dca, caddr_t buf, int flen, int tlen, int private)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_pkcs1_padding: tlen: %d, flen: %d: private: %d\n",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Padding for private encrypt */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Padding for public encrypt */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_random_buffer(dca, &buf[flen+1], tlen - flen - 3) !=
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_pkcs1_unpadding(char *buf, int *tlen, int flen, int mode)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm const unsigned char *p;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DENTRY, "dca_pkcs1_unpadding: tlen: %d, flen: %d\n",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (*(p--) != 0)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* It is ok if the data length is 0 after removing the padding */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (*p != 0xff) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (*p == '\0') {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (*p == '\0') {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* i < 0 means did not find the end of the padding */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (i < 0)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return decrypt_error_code(mode, CRYPTO_ENCRYPTED_DATA_INVALID,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (i > *tlen) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Return the unpadded length to the caller */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For RSA_X_509 padding and unpadding, pad all 0s before actual data.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Note that the data will be in reverse order.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DENTRY, "dca_x509_padding: tlen: %d, flen: %d\n",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/* ARGSUSED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_x509_unpadding(char *buf, int tlen, int flen, int mode)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm const unsigned char *p;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DENTRY, "dca_x509_unpadding: tlen: %d, flen: %d\n",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (*(--p) != 0)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int decrypt_error_code(int mode, int decrypt, int verify, int def)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm switch (mode) {