2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <modes/modes.h>
2N/A#include <sys/crypto/common.h>
2N/A#include <sys/crypto/spi.h>
2N/A#include <cryptoutil.h>
2N/A#include <syslog.h>
2N/A#define _AES_FIPS_POST
2N/A#define _RSA_FIPS_POST
2N/A#include <aes/aes_impl.h>
2N/A#include <rsa/rsa_impl.h>
2N/A#include <padding/padding.h>
2N/A#include "libsoftcrypto.h"
2N/A
2N/A/*
2N/A * IMPORTANT: Each feature enhancement must be accompanied by an increment
2N/A * in the version.
2N/A */
2N/A#define UCRYPTO_VERSION 4
2N/A
2N/Atypedef enum ucrypto_op {
2N/A UCRYPTO_NOOP = 0,
2N/A UCRYPTO_ENCRYPT,
2N/A UCRYPTO_DECRYPT,
2N/A UCRYPTO_SIGN,
2N/A UCRYPTO_VERIFY
2N/A} ucrypto_op_t;
2N/A
2N/Atypedef struct ucrypto_ctx {
2N/A ucrypto_mech_t mech;
2N/A uint8_t blocksize; /* for padding, blocksize multiple */
2N/A uint8_t remain; /* for padding, remainder % blocksize */
2N/A} ucrypto_ctx_t;
2N/A
2N/Astatic int ucrypto_common_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
2N/A uchar_t *key_str, size_t key_len, void *iv, size_t iv_len,
2N/A ucrypto_op_t op_type);
2N/Astatic int ucrypto_common_update(crypto_ctx_t *context, uchar_t *in,
2N/A size_t in_len, uchar_t *out, size_t *out_len, ucrypto_op_t op_type);
2N/Astatic int ucrypto_common_final(crypto_ctx_t *context, uchar_t *out,
2N/A size_t *out_len, ucrypto_op_t op_type);
2N/Astatic int ucrypto_atomic(ucrypto_mech_t mech_type, uchar_t *key_str,
2N/A size_t key_len, void *iv, size_t iv_len, uchar_t *in, size_t in_len,
2N/A uchar_t *out, size_t *out_len, ucrypto_op_t op_type);
2N/A
2N/Astatic int create_context(crypto_ctx_t *context, crypto_key_t key,
2N/A crypto_mechanism_t mech, ucrypto_op_t op_type);
2N/Astatic void free_context(crypto_ctx_t *context);
2N/Astatic int set_key(crypto_key_t *key, void *key_data, size_t key_len,
2N/A ucrypto_mech_t mech_type);
2N/Astatic int set_mechanism(crypto_mechanism_t *mech, ucrypto_mech_t mech_type,
2N/A void *iv, size_t iv_len);
2N/A
2N/A#pragma init(ucrypto_init)
2N/Astatic void ucrypto_init();
2N/A
2N/A#pragma inline(create_context)
2N/Astatic int
2N/Acreate_context(crypto_ctx_t *context, crypto_key_t key, crypto_mechanism_t mech,
2N/A ucrypto_op_t op_type)
2N/A{
2N/A int rv;
2N/A ucrypto_ctx_t *uctx = NULL;
2N/A int blocksize;
2N/A
2N/A switch (mech.cm_type) {
2N/A
2N/A case CRYPTO_AES_CBC_PAD:
2N/A blocksize = AES_BLOCK_LEN; /* i.e., padding needed */
2N/A mech.cm_type = CRYPTO_AES_CBC; /* remapped */
2N/A break;
2N/A
2N/A default:
2N/A blocksize = 0; /* i.e., no padding needed */
2N/A break;
2N/A
2N/A }
2N/A
2N/A switch (mech.cm_type) {
2N/A
2N/A case CRYPTO_AES_ECB:
2N/A case CRYPTO_AES_CBC:
2N/A case CRYPTO_AES_CTR:
2N/A case CRYPTO_AES_CCM:
2N/A case CRYPTO_AES_GCM:
2N/A case CRYPTO_AES_CFB128:
2N/A case CRYPTO_AES_XTS:
2N/A /* UCRYPTO_SIGN and UCRYPTO_VERIFY ops are invalid here */
2N/A if (op_type == UCRYPTO_SIGN || op_type == UCRYPTO_VERIFY) {
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A break;
2N/A }
2N/A
2N/A context->cc_flags |= CRYPTO_PROVIDER_PRIVATE_HAS_FUNCS;
2N/A rv = aes_common_init(context, &mech, &key, NULL, NULL,
2N/A (op_type == UCRYPTO_ENCRYPT) ? B_TRUE : B_FALSE);
2N/A break;
2N/A
2N/A case CRYPTO_RSA_PKCS:
2N/A case CRYPTO_RSA_X_509:
2N/A case CRYPTO_MD5_RSA_PKCS:
2N/A case CRYPTO_SHA1_RSA_PKCS:
2N/A case CRYPTO_SHA224_RSA_PKCS:
2N/A case CRYPTO_SHA256_RSA_PKCS:
2N/A case CRYPTO_SHA384_RSA_PKCS:
2N/A case CRYPTO_SHA512_RSA_PKCS:
2N/A /* UCRYPTO_ENCRYPT and UCRYPTO_DECRYPT ops are invalid here */
2N/A if (op_type == UCRYPTO_ENCRYPT || op_type == UCRYPTO_DECRYPT) {
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A break;
2N/A }
2N/A
2N/A rv = rsaprov_sign_verify_common_init(context, &mech, &key,
2N/A NULL, NULL);
2N/A break;
2N/A
2N/A default:
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A }
2N/A
2N/A if (rv != CRYPTO_SUCCESS)
2N/A return (rv);
2N/A
2N/A /* Create framework context */
2N/A uctx = malloc(sizeof (ucrypto_ctx_t));
2N/A if (uctx == NULL)
2N/A return (CRYPTO_HOST_MEMORY);
2N/A
2N/A uctx->mech = mech.cm_type;
2N/A uctx->blocksize = blocksize; /* constant based on mech type */
2N/A uctx->remain = 0; /* continuously updated with input */
2N/A
2N/A context->cc_framework_private = uctx;
2N/A
2N/A return (CRYPTO_SUCCESS);
2N/A}
2N/A
2N/A/*
2N/A * This function frees the context for ucrypto, not for the provider
2N/A * the module code handles that.
2N/A */
2N/A#pragma inline(free_context)
2N/Astatic void
2N/Afree_context(crypto_ctx_t *context)
2N/A{
2N/A ucrypto_ctx_t *uctx = (ucrypto_ctx_t *)(context->cc_framework_private);
2N/A
2N/A if (uctx != NULL)
2N/A free(uctx);
2N/A
2N/A context->cc_framework_private = NULL;
2N/A}
2N/A
2N/A#pragma inline(set_key)
2N/Astatic int
2N/Aset_key(crypto_key_t *key, void *key_data, size_t key_len,
2N/A ucrypto_mech_t mech_type)
2N/A{
2N/A switch (mech_type) {
2N/A
2N/A case CRYPTO_AES_ECB:
2N/A case CRYPTO_AES_CBC:
2N/A case CRYPTO_AES_CBC_PAD:
2N/A case CRYPTO_AES_CTR:
2N/A case CRYPTO_AES_CCM:
2N/A case CRYPTO_AES_GCM:
2N/A case CRYPTO_AES_CFB128:
2N/A case CRYPTO_AES_XTS:
2N/A case CRYPTO_AES_XCBC_MAC:
2N/A key->ck_format = CRYPTO_KEY_RAW;
2N/A key->ck_data = key_data;
2N/A key->ck_length = CRYPTO_BYTES2BITS(key_len);
2N/A break;
2N/A
2N/A case CRYPTO_RSA_PKCS:
2N/A case CRYPTO_RSA_X_509:
2N/A case CRYPTO_MD5_RSA_PKCS:
2N/A case CRYPTO_SHA1_RSA_PKCS:
2N/A case CRYPTO_SHA224_RSA_PKCS:
2N/A case CRYPTO_SHA256_RSA_PKCS:
2N/A case CRYPTO_SHA384_RSA_PKCS:
2N/A case CRYPTO_SHA512_RSA_PKCS:
2N/A key->ck_format = CRYPTO_KEY_ATTR_LIST;
2N/A key->ck_attrs = (crypto_object_attribute_t *)key_data;
2N/A key->ck_count = key_len;
2N/A break;
2N/A
2N/A default:
2N/A return (CRYPTO_MECH_NOT_SUPPORTED);
2N/A }
2N/A
2N/A return (CRYPTO_SUCCESS);
2N/A}
2N/A
2N/A/*
2N/A * If the mechanism is defined in this function, then it is supported.
2N/A * If it is supported, sets up the initialization vector in crypto_mechanism_t.
2N/A */
2N/A#pragma inline(set_mechanism)
2N/Astatic int
2N/Aset_mechanism(crypto_mechanism_t *mech, ucrypto_mech_t mech_type,
2N/A void *iv, size_t iv_len)
2N/A{
2N/A if (mech_type == CRYPTO_AES_ECB && iv_len != 0)
2N/A return (CRYPTO_MECHANISM_PARAM_INVALID);
2N/A
2N/A mech->cm_type = mech_type;
2N/A mech->cm_param = (char *)iv;
2N/A mech->cm_param_len = iv_len;
2N/A return (CRYPTO_SUCCESS);
2N/A}
2N/A
2N/A/* Return the version of this library */
2N/Aint
2N/Aucrypto_version(void)
2N/A{
2N/A return (UCRYPTO_VERSION);
2N/A}
2N/A
2N/A/*
2N/A * UCRYPTO common internal functions.
2N/A */
2N/A
2N/A#pragma inline(ucrypto_common_init)
2N/Astatic int
2N/Aucrypto_common_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
2N/A uchar_t *key_str, size_t key_len, void *iv, size_t iv_len,
2N/A ucrypto_op_t op_type)
2N/A{
2N/A int rv;
2N/A crypto_key_t key = { 0 };
2N/A crypto_mechanism_t mech = { 0 };
2N/A
2N/A rv = set_mechanism(&mech, mech_type, iv, iv_len);
2N/A if (rv != CRYPTO_SUCCESS)
2N/A return (rv);
2N/A
2N/A rv = set_key(&key, key_str, key_len, mech_type);
2N/A if (rv != CRYPTO_SUCCESS)
2N/A return (rv);
2N/A
2N/A rv = create_context(context, key, mech, op_type);
2N/A if (rv != CRYPTO_SUCCESS)
2N/A return (rv);
2N/A
2N/A return (CRYPTO_SUCCESS);
2N/A}
2N/A
2N/A#pragma inline(ucrypto_common_update)
2N/Astatic int
2N/Aucrypto_common_update(crypto_ctx_t *context, uchar_t *in, size_t in_len,
2N/A uchar_t *out, size_t *out_len, ucrypto_op_t op_type)
2N/A{
2N/A int rv;
2N/A crypto_data_t idata = { 0 };
2N/A crypto_data_t odata = { 0 };
2N/A ucrypto_ctx_t *uctx = (ucrypto_ctx_t *)(context->cc_framework_private);
2N/A
2N/A CRYPTO_SET_RAW_DATA(idata, in, in_len);
2N/A
2N/A switch (uctx->mech) {
2N/A
2N/A case CRYPTO_AES_ECB:
2N/A case CRYPTO_AES_CBC:
2N/A case CRYPTO_AES_CTR:
2N/A case CRYPTO_AES_CCM:
2N/A case CRYPTO_AES_GCM:
2N/A case CRYPTO_AES_CFB128:
2N/A case CRYPTO_AES_XTS:
2N/A if (out_len == NULL) {
2N/A rv = CRYPTO_ARGUMENTS_BAD;
2N/A goto cleanup;
2N/A }
2N/A
2N/A CRYPTO_SET_RAW_DATA(odata, out, *out_len);
2N/A
2N/A if (op_type == UCRYPTO_ENCRYPT)
2N/A rv = aes_encrypt_update(context, &idata, &odata, NULL);
2N/A else if (op_type == UCRYPTO_DECRYPT)
2N/A rv = aes_decrypt_update(context, &idata, &odata, NULL);
2N/A else
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A if (rv != CRYPTO_SUCCESS)
2N/A goto cleanup;
2N/A
2N/A *out_len = odata.cd_length;
2N/A
2N/A break;
2N/A
2N/A case CRYPTO_RSA_PKCS:
2N/A case CRYPTO_RSA_X_509:
2N/A case CRYPTO_MD5_RSA_PKCS:
2N/A case CRYPTO_SHA1_RSA_PKCS:
2N/A case CRYPTO_SHA224_RSA_PKCS:
2N/A case CRYPTO_SHA256_RSA_PKCS:
2N/A case CRYPTO_SHA384_RSA_PKCS:
2N/A case CRYPTO_SHA512_RSA_PKCS:
2N/A if (op_type == UCRYPTO_SIGN)
2N/A rv = rsaprov_sign_update(context, &idata, NULL);
2N/A else if (op_type == UCRYPTO_VERIFY)
2N/A rv = rsaprov_verify_update(context, &idata, NULL);
2N/A else
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A if (rv != CRYPTO_SUCCESS)
2N/A goto cleanup;
2N/A break;
2N/A
2N/A default:
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A goto cleanup;
2N/A }
2N/A
2N/A /* Reset remainder bytes for padded mechs only if update successful. */
2N/A if (uctx->blocksize != 0)
2N/A uctx->remain = ((uctx->remain + in_len) % uctx->blocksize);
2N/A
2N/A return (CRYPTO_SUCCESS);
2N/A
2N/Acleanup:
2N/A free_context(context);
2N/A return (rv);
2N/A}
2N/A
2N/A#pragma inline(ucrypto_common_final)
2N/Astatic int
2N/Aucrypto_common_final(crypto_ctx_t *context, uchar_t *out, size_t *out_len,
2N/A ucrypto_op_t op_type)
2N/A{
2N/A int rv;
2N/A crypto_data_t odata = { 0 };
2N/A ucrypto_ctx_t *uctx = (ucrypto_ctx_t *)(context->cc_framework_private);
2N/A
2N/A if (out_len == NULL) {
2N/A rv = CRYPTO_ARGUMENTS_BAD;
2N/A goto cleanup;
2N/A }
2N/A
2N/A CRYPTO_SET_RAW_DATA(odata, out, *out_len);
2N/A
2N/A switch (uctx->mech) {
2N/A
2N/A case CRYPTO_AES_ECB:
2N/A case CRYPTO_AES_CBC:
2N/A case CRYPTO_AES_CTR:
2N/A case CRYPTO_AES_CCM:
2N/A case CRYPTO_AES_GCM:
2N/A case CRYPTO_AES_CFB128:
2N/A case CRYPTO_AES_XTS:
2N/A /*
2N/A * If this is a padded mech, do one more update op on the
2N/A * padding buffer instead of the final op; the padding will
2N/A * guarantee no more residual data, so the final op becomes
2N/A * unnecessary.
2N/A */
2N/A if (op_type == UCRYPTO_ENCRYPT && uctx->blocksize != 0) {
2N/A crypto_data_t idata = { 0 };
2N/A uint8_t padded[AES_BLOCK_LEN]; /* longest blocksize */
2N/A size_t extra = uctx->blocksize - uctx->remain;
2N/A
2N/A (void) pkcs7_encode(NULL, uctx->remain, padded, extra,
2N/A uctx->blocksize);
2N/A
2N/A CRYPTO_SET_RAW_DATA(idata, padded, extra);
2N/A
2N/A /*
2N/A * Remember, mechs were remapped to their unpadded
2N/A * counterparts; blocksize != 0 means padded mech.
2N/A */
2N/A switch (uctx->mech) {
2N/A case CRYPTO_AES_CBC:
2N/A rv = aes_encrypt_update(context, &idata,
2N/A &odata, NULL);
2N/A break;
2N/A
2N/A default:
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A break;
2N/A }
2N/A if (rv != CRYPTO_SUCCESS)
2N/A goto cleanup;
2N/A } else if (op_type == UCRYPTO_DECRYPT && uctx->blocksize != 0) {
2N/A if (uctx->remain != 0) {
2N/A rv = CRYPTO_ENCRYPTED_DATA_INVALID;
2N/A goto cleanup;
2N/A }
2N/A }
2N/A
2N/A if (op_type == UCRYPTO_ENCRYPT)
2N/A rv = aes_encrypt_final(context, &odata, NULL);
2N/A else if (op_type == UCRYPTO_DECRYPT)
2N/A rv = aes_decrypt_final(context, &odata, NULL);
2N/A else
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A if (rv != CRYPTO_SUCCESS)
2N/A goto cleanup;
2N/A
2N/A if (op_type == UCRYPTO_DECRYPT && uctx->blocksize != 0) {
2N/A if (pkcs7_decode(out, &(odata.cd_length)) != 0) {
2N/A rv = CRYPTO_ENCRYPTED_DATA_INVALID;
2N/A goto cleanup;
2N/A }
2N/A }
2N/A break;
2N/A
2N/A case CRYPTO_RSA_PKCS:
2N/A case CRYPTO_RSA_X_509:
2N/A case CRYPTO_MD5_RSA_PKCS:
2N/A case CRYPTO_SHA1_RSA_PKCS:
2N/A case CRYPTO_SHA224_RSA_PKCS:
2N/A case CRYPTO_SHA256_RSA_PKCS:
2N/A case CRYPTO_SHA384_RSA_PKCS:
2N/A case CRYPTO_SHA512_RSA_PKCS:
2N/A if (op_type == UCRYPTO_SIGN)
2N/A rv = rsaprov_sign_final(context, &odata, NULL);
2N/A else if (op_type == UCRYPTO_VERIFY)
2N/A rv = rsaprov_verify_final(context, &odata, NULL);
2N/A else
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A if (rv != CRYPTO_SUCCESS)
2N/A goto cleanup;
2N/A break;
2N/A
2N/A default:
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A goto cleanup;
2N/A }
2N/A
2N/A *out_len = odata.cd_length;
2N/A
2N/Acleanup:
2N/A
2N/A free_context(context);
2N/A return (rv);
2N/A}
2N/A
2N/A
2N/A#pragma inline(ucrypto_atomic)
2N/Astatic int
2N/Aucrypto_atomic(ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
2N/A void *iv, size_t iv_len, uchar_t *in, size_t in_len,
2N/A uchar_t *out, size_t *out_len, ucrypto_op_t op_type)
2N/A{
2N/A int rv;
2N/A crypto_mechanism_t mech = { 0 };
2N/A crypto_data_t idata = { 0 };
2N/A crypto_data_t odata = { 0 };
2N/A crypto_key_t key = { 0 };
2N/A uchar_t *padded = NULL;
2N/A size_t padded_len;
2N/A size_t extra;
2N/A
2N/A if (out_len == NULL)
2N/A return (CRYPTO_ARGUMENTS_BAD);
2N/A
2N/A switch (mech_type) {
2N/A
2N/A case CRYPTO_AES_CBC_PAD:
2N/A if (op_type == UCRYPTO_ENCRYPT) {
2N/A extra = AES_BLOCK_LEN - (in_len % AES_BLOCK_LEN);
2N/A if (*out_len - in_len < extra)
2N/A return (CRYPTO_BUFFER_TOO_SMALL);
2N/A
2N/A /*
2N/A * Copy data to allocated buffer big enough to hold
2N/A * it plus extra padding.
2N/A */
2N/A padded_len = in_len + extra;
2N/A padded = malloc(padded_len);
2N/A if (padded == NULL)
2N/A return (CRYPTO_HOST_MEMORY);
2N/A (void) pkcs7_encode(in, in_len, padded, padded_len,
2N/A AES_BLOCK_LEN);
2N/A
2N/A mech_type = CRYPTO_AES_CBC;
2N/A } else if (op_type == UCRYPTO_DECRYPT) {
2N/A /*
2N/A * Copy data to temporary allocated buffer.
2N/A */
2N/A padded_len = *out_len;
2N/A padded = malloc(padded_len);
2N/A if (padded == NULL)
2N/A return (CRYPTO_HOST_MEMORY);
2N/A bzero(padded, padded_len); /* out could be NULL */
2N/A (void) memcpy(padded, out, *out_len);
2N/A
2N/A mech_type = CRYPTO_AES_CBC;
2N/A } else
2N/A return (CRYPTO_MECH_NOT_SUPPORTED);
2N/A break;
2N/A
2N/A default:
2N/A break;
2N/A }
2N/A
2N/A rv = set_mechanism(&mech, mech_type, iv, iv_len);
2N/A if (rv != CRYPTO_SUCCESS)
2N/A goto out_atomic;
2N/A
2N/A rv = set_key(&key, key_str, key_len, mech_type);
2N/A if (rv != CRYPTO_SUCCESS)
2N/A goto out_atomic;
2N/A
2N/A if (op_type == UCRYPTO_ENCRYPT && padded != NULL) {
2N/A CRYPTO_SET_RAW_DATA(idata, padded, padded_len);
2N/A } else {
2N/A CRYPTO_SET_RAW_DATA(idata, in, in_len);
2N/A }
2N/A if (op_type == UCRYPTO_DECRYPT && padded != NULL) {
2N/A CRYPTO_SET_RAW_DATA(odata, padded, padded_len);
2N/A } else {
2N/A CRYPTO_SET_RAW_DATA(odata, out, *out_len);
2N/A }
2N/A
2N/A switch (mech_type) {
2N/A
2N/A case CRYPTO_AES_ECB:
2N/A case CRYPTO_AES_CBC:
2N/A case CRYPTO_AES_CTR:
2N/A case CRYPTO_AES_CCM:
2N/A case CRYPTO_AES_GCM:
2N/A case CRYPTO_AES_CFB128:
2N/A case CRYPTO_AES_XTS:
2N/A case CRYPTO_AES_XCBC_MAC:
2N/A if (op_type == UCRYPTO_ENCRYPT)
2N/A rv = aes_encrypt_atomic(NULL, NULL, &mech, &key,
2N/A &idata, &odata, NULL, NULL);
2N/A else if (op_type == UCRYPTO_DECRYPT)
2N/A rv = aes_decrypt_atomic(NULL, NULL, &mech, &key,
2N/A &idata, &odata, NULL, NULL);
2N/A else
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A break;
2N/A
2N/A case CRYPTO_RSA_PKCS:
2N/A case CRYPTO_RSA_X_509:
2N/A case CRYPTO_MD5_RSA_PKCS:
2N/A case CRYPTO_SHA1_RSA_PKCS:
2N/A case CRYPTO_SHA224_RSA_PKCS:
2N/A case CRYPTO_SHA256_RSA_PKCS:
2N/A case CRYPTO_SHA384_RSA_PKCS:
2N/A case CRYPTO_SHA512_RSA_PKCS:
2N/A if (op_type == UCRYPTO_ENCRYPT)
2N/A rv = rsaprov_encrypt_atomic(NULL, NULL, &mech,
2N/A &key, &idata, &odata, NULL, NULL);
2N/A else if (op_type == UCRYPTO_DECRYPT)
2N/A rv = rsaprov_decrypt_atomic(NULL, NULL, &mech,
2N/A &key, &idata, &odata, NULL, NULL);
2N/A else if (op_type == UCRYPTO_SIGN)
2N/A rv = rsaprov_sign_atomic(NULL, NULL, &mech,
2N/A &key, &idata, &odata, NULL, NULL);
2N/A else if (op_type == UCRYPTO_VERIFY)
2N/A rv = rsaprov_verify_atomic(NULL, NULL, &mech,
2N/A &key, &idata, &odata, NULL, NULL);
2N/A else
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A break;
2N/A
2N/A default:
2N/A rv = CRYPTO_MECH_NOT_SUPPORTED;
2N/A break;
2N/A }
2N/A
2N/A if (op_type == UCRYPTO_DECRYPT && padded != NULL) {
2N/A if (pkcs7_decode(padded, &padded_len) != 0) {
2N/A rv = CRYPTO_ENCRYPTED_DATA_INVALID;
2N/A goto out_atomic;
2N/A }
2N/A
2N/A odata.cd_length = padded_len;
2N/A
2N/A if (out != NULL)
2N/A (void) memcpy(out, padded, padded_len);
2N/A }
2N/A
2N/A *out_len = odata.cd_length;
2N/A
2N/Aout_atomic:
2N/A if (padded != NULL)
2N/A free(padded);
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * UCRYPTO exported functions.
2N/A */
2N/A
2N/A/* Encrypt API */
2N/Aint
2N/Aucrypto_encrypt_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
2N/A uchar_t *key_str, size_t key_len, void *iv, size_t iv_len)
2N/A{
2N/A return (ucrypto_common_init(context, mech_type, key_str, key_len,
2N/A iv, iv_len, UCRYPTO_ENCRYPT));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_encrypt_update(crypto_ctx_t *context, uchar_t *in, size_t in_len,
2N/A uchar_t *out, size_t *out_len)
2N/A{
2N/A rawdata_crypt_update_function_t *update_func;
2N/A
2N/A if (context->cc_flags & CRYPTO_PROVIDER_PRIVATE_HAS_FUNCS) {
2N/A update_func =
2N/A ((rawdata_funcs_and_ctx_t *)
2N/A (context->cc_provider_private))->crypt_funcs.encrypt_update;
2N/A if (update_func != NULL) {
2N/A return (update_func(context, in, in_len, out, out_len));
2N/A } else {
2N/A context->cc_flags &= ~CRYPTO_PROVIDER_PRIVATE_HAS_FUNCS;
2N/A context->cc_provider_private =
2N/A ((rawdata_funcs_and_ctx_t *)
2N/A (context->cc_provider_private))->ctx;
2N/A }
2N/A }
2N/A
2N/A return (ucrypto_common_update(context, in, in_len, out, out_len,
2N/A UCRYPTO_ENCRYPT));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_encrypt_final(crypto_ctx_t *context, uchar_t *out, size_t *out_len)
2N/A{
2N/A return (ucrypto_common_final(context, out, out_len, UCRYPTO_ENCRYPT));
2N/A}
2N/A
2N/A
2N/A#define GET_RAWDATA_FUNCS(mech_type) \
2N/A switch (mech_type) { \
2N/A case CRYPTO_AES_CBC: \
2N/A case CRYPTO_AES_ECB: \
2N/A case CRYPTO_AES_CFB128: \
2N/A case CRYPTO_AES_CTR: \
2N/A funcs = rawdata_get_aes_funcs(mech_type); \
2N/A break; \
2N/A default: \
2N/A funcs = NULL; \
2N/A break; \
2N/A }
2N/A
2N/A
2N/Aint
2N/Aucrypto_encrypt(ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
2N/A void *iv, size_t iv_len, uchar_t *in, size_t in_len,
2N/A uchar_t *out, size_t *out_len)
2N/A{
2N/A rawdata_crypt_functions_t *funcs;
2N/A
2N/A GET_RAWDATA_FUNCS(mech_type);
2N/A
2N/A if (funcs) {
2N/A rawdata_crypt_function_t *encr_func;
2N/A encr_func = funcs->encrypt;
2N/A if (encr_func != NULL) {
2N/A return (encr_func(key_str, key_len, iv, iv_len,
2N/A in, in_len, out, out_len));
2N/A }
2N/A }
2N/A
2N/A return (ucrypto_atomic(mech_type, key_str, key_len, iv, iv_len, in,
2N/A in_len, out, out_len, UCRYPTO_ENCRYPT));
2N/A}
2N/A
2N/A/* Decrypt API */
2N/Aint
2N/Aucrypto_decrypt_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
2N/A uchar_t *key_str, size_t key_len, void *iv, size_t iv_len)
2N/A{
2N/A return (ucrypto_common_init(context, mech_type, key_str, key_len,
2N/A iv, iv_len, UCRYPTO_DECRYPT));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_decrypt_update(crypto_ctx_t *context, uchar_t *in, size_t in_len,
2N/A uchar_t *out, size_t *out_len)
2N/A{
2N/A rawdata_crypt_update_function_t *update_func;
2N/A
2N/A if (context->cc_flags & CRYPTO_PROVIDER_PRIVATE_HAS_FUNCS) {
2N/A update_func =
2N/A ((rawdata_funcs_and_ctx_t *)
2N/A (context->cc_provider_private))->crypt_funcs.decrypt_update;
2N/A if (update_func != NULL) {
2N/A return (update_func(context, in, in_len, out, out_len));
2N/A } else {
2N/A context->cc_flags &= ~CRYPTO_PROVIDER_PRIVATE_HAS_FUNCS;
2N/A context->cc_provider_private =
2N/A ((rawdata_funcs_and_ctx_t *)
2N/A (context->cc_provider_private))->ctx;
2N/A }
2N/A }
2N/A
2N/A return (ucrypto_common_update(context, in, in_len, out, out_len,
2N/A UCRYPTO_DECRYPT));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_decrypt_final(crypto_ctx_t *context, uchar_t *out, size_t *out_len)
2N/A{
2N/A return (ucrypto_common_final(context, out, out_len, UCRYPTO_DECRYPT));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_decrypt(ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
2N/A void *iv, size_t iv_len, uchar_t *in, size_t in_len,
2N/A uchar_t *out, size_t *out_len)
2N/A{
2N/A rawdata_crypt_functions_t *funcs;
2N/A
2N/A GET_RAWDATA_FUNCS(mech_type);
2N/A if (funcs) {
2N/A rawdata_crypt_function_t *decr_func;
2N/A decr_func = funcs->decrypt;
2N/A if (decr_func != NULL) {
2N/A return (decr_func(key_str, key_len, iv, iv_len,
2N/A in, in_len, out, out_len));
2N/A }
2N/A }
2N/A
2N/A return (ucrypto_atomic(mech_type, key_str, key_len, iv, iv_len, in,
2N/A in_len, out, out_len, UCRYPTO_DECRYPT));
2N/A}
2N/A
2N/A/* Sign API */
2N/Aint
2N/Aucrypto_sign_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
2N/A uchar_t *key_str, size_t key_len, void *iv, size_t iv_len)
2N/A{
2N/A return (ucrypto_common_init(context, mech_type, key_str, key_len,
2N/A iv, iv_len, UCRYPTO_SIGN));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_sign_update(crypto_ctx_t *context, uchar_t *data_str, size_t data_len)
2N/A{
2N/A return (ucrypto_common_update(context, data_str, data_len,
2N/A NULL, NULL, UCRYPTO_SIGN));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_sign_final(crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len)
2N/A{
2N/A return (ucrypto_common_final(context, sig_str, sig_len,
2N/A UCRYPTO_SIGN));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_sign(ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
2N/A void *iv, size_t iv_len, uchar_t *data_str, size_t data_len,
2N/A uchar_t *sig_str, size_t *sig_len)
2N/A{
2N/A return (ucrypto_atomic(mech_type, key_str, key_len, iv, iv_len,
2N/A data_str, data_len, sig_str, sig_len, UCRYPTO_SIGN));
2N/A}
2N/A
2N/A/* Verify API */
2N/Aint
2N/Aucrypto_verify_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
2N/A uchar_t *key_str, size_t key_len, void *iv, size_t iv_len)
2N/A{
2N/A return (ucrypto_common_init(context, mech_type, key_str, key_len,
2N/A iv, iv_len, UCRYPTO_VERIFY));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_verify_update(crypto_ctx_t *context, uchar_t *data_str, size_t data_len)
2N/A{
2N/A return (ucrypto_common_update(context, data_str, data_len,
2N/A NULL, NULL, UCRYPTO_VERIFY));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_verify_final(crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len)
2N/A{
2N/A return (ucrypto_common_final(context, sig_str, sig_len,
2N/A UCRYPTO_VERIFY));
2N/A}
2N/A
2N/Aint
2N/Aucrypto_verify(ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
2N/A void *iv, size_t iv_len, uchar_t *data_str, size_t data_len,
2N/A uchar_t *sig_str, size_t *sig_len)
2N/A{
2N/A return (ucrypto_atomic(mech_type, key_str, key_len, iv, iv_len,
2N/A data_str, data_len, sig_str, sig_len, UCRYPTO_VERIFY));
2N/A}
2N/A
2N/Astatic void
2N/Aucrypto_init()
2N/A{
2N/A
2N/A int ucrypto_fips_mode = CRYPTO_FIPS_MODE_DISABLED;
2N/A int rv;
2N/A
2N/A /*
2N/A * Perform POST when fips mode is enabled.
2N/A */
2N/A (void) get_fips_mode(&ucrypto_fips_mode);
2N/A if (ucrypto_fips_mode == CRYPTO_FIPS_MODE_ENABLED) {
2N/A /* AES Power-On SelfTest for 128-bit key. */
2N/A if ((rv = fips_aes_post(FIPS_AES_128_KEY_SIZE)) != 0) {
2N/A syslog(LOG_ERR, "ucrypto_init: FIPS-140 Power On Self "
2N/A "Test (AES-128) failed, rv= %d", rv);
2N/A abort();
2N/A }
2N/A
2N/A /* AES Power-On SelfTest for 192-bit key. */
2N/A if ((rv = fips_aes_post(FIPS_AES_192_KEY_SIZE)) != 0) {
2N/A syslog(LOG_ERR, "ucrypto_init: FIPS-140 Power On Self "
2N/A "Test (AES-192) failed, rv= %d", rv);
2N/A abort();
2N/A }
2N/A
2N/A /* AES Power-On SelfTest for 256-bit key. */
2N/A if ((rv = fips_aes_post(FIPS_AES_256_KEY_SIZE)) != 0) {
2N/A syslog(LOG_ERR, "ucrypto_init: FIPS-140 Power On Self "
2N/A "Test (AES-256) failed, rv= %d", rv);
2N/A abort();
2N/A }
2N/A
2N/A /*
2N/A * RSA Power-On SelfTest
2N/A */
2N/A if ((rv = fips_rsa_post()) != 0) {
2N/A syslog(LOG_ERR, "ucrypto_init: FIPS-140 Power On Self "
2N/A "Test (RSA) failed, rv= %d", rv);
2N/A abort();
2N/A }
2N/A
2N/A }
2N/A}