diff options
author | Tom Caputi <[email protected]> | 2016-05-12 10:51:24 -0400 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-07-20 10:43:30 -0700 |
commit | 0b04990a5de594659d2cf20458965277dd6efeb1 (patch) | |
tree | 74369a3236e03359f7276cb9b19687e28c7f6d59 /module/icp/include | |
parent | be88e733a634ad0d7f20350e1a17ede51922d3ff (diff) |
Illumos Crypto Port module added to enable native encryption in zfs
A port of the Illumos Crypto Framework to a Linux kernel module (found
in module/icp). This is needed to do the actual encryption work. We cannot
use the Linux kernel's built in crypto api because it is only exported to
GPL-licensed modules. Having the ICP also means the crypto code can run on
any of the other kernels under OpenZFS. I ended up porting over most of the
internals of the framework, which means that porting over other API calls (if
we need them) should be fairly easy. Specifically, I have ported over the API
functions related to encryption, digests, macs, and crypto templates. The ICP
is able to use assembly-accelerated encryption on amd64 machines and AES-NI
instructions on Intel chips that support it. There are place-holder
directories for similar assembly optimizations for other architectures
(although they have not been written).
Signed-off-by: Tom Caputi <[email protected]>
Signed-off-by: Tony Hutter <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Issue #4329
Diffstat (limited to 'module/icp/include')
25 files changed, 7756 insertions, 0 deletions
diff --git a/module/icp/include/aes/aes_impl.h b/module/icp/include/aes/aes_impl.h new file mode 100644 index 000000000..ed15f74e7 --- /dev/null +++ b/module/icp/include/aes/aes_impl.h @@ -0,0 +1,170 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _AES_IMPL_H +#define _AES_IMPL_H + +/* + * Common definitions used by AES. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/zfs_context.h> +#include <sys/crypto/common.h> + +/* Similar to sysmacros.h IS_P2ALIGNED, but checks two pointers: */ +#define IS_P2ALIGNED2(v, w, a) \ + ((((uintptr_t)(v) | (uintptr_t)(w)) & ((uintptr_t)(a) - 1)) == 0) + +#define AES_BLOCK_LEN 16 /* bytes */ +/* Round constant length, in number of 32-bit elements: */ +#define RC_LENGTH (5 * ((AES_BLOCK_LEN) / 4 - 2)) + +#define AES_COPY_BLOCK(src, dst) \ + (dst)[0] = (src)[0]; \ + (dst)[1] = (src)[1]; \ + (dst)[2] = (src)[2]; \ + (dst)[3] = (src)[3]; \ + (dst)[4] = (src)[4]; \ + (dst)[5] = (src)[5]; \ + (dst)[6] = (src)[6]; \ + (dst)[7] = (src)[7]; \ + (dst)[8] = (src)[8]; \ + (dst)[9] = (src)[9]; \ + (dst)[10] = (src)[10]; \ + (dst)[11] = (src)[11]; \ + (dst)[12] = (src)[12]; \ + (dst)[13] = (src)[13]; \ + (dst)[14] = (src)[14]; \ + (dst)[15] = (src)[15] + +#define AES_XOR_BLOCK(src, dst) \ + (dst)[0] ^= (src)[0]; \ + (dst)[1] ^= (src)[1]; \ + (dst)[2] ^= (src)[2]; \ + (dst)[3] ^= (src)[3]; \ + (dst)[4] ^= (src)[4]; \ + (dst)[5] ^= (src)[5]; \ + (dst)[6] ^= (src)[6]; \ + (dst)[7] ^= (src)[7]; \ + (dst)[8] ^= (src)[8]; \ + (dst)[9] ^= (src)[9]; \ + (dst)[10] ^= (src)[10]; \ + (dst)[11] ^= (src)[11]; \ + (dst)[12] ^= (src)[12]; \ + (dst)[13] ^= (src)[13]; \ + (dst)[14] ^= (src)[14]; \ + (dst)[15] ^= (src)[15] + +/* AES key size definitions */ +#define AES_MINBITS 128 +#define AES_MINBYTES ((AES_MINBITS) >> 3) +#define AES_MAXBITS 256 +#define AES_MAXBYTES ((AES_MAXBITS) >> 3) + +#define AES_MIN_KEY_BYTES ((AES_MINBITS) >> 3) +#define AES_MAX_KEY_BYTES ((AES_MAXBITS) >> 3) +#define AES_192_KEY_BYTES 24 +#define AES_IV_LEN 16 + +/* AES key schedule may be implemented with 32- or 64-bit elements: */ +#define AES_32BIT_KS 32 +#define AES_64BIT_KS 64 + +#define MAX_AES_NR 14 /* Maximum number of rounds */ +#define MAX_AES_NB 4 /* Number of columns comprising a state */ + +typedef union { +#ifdef sun4u + uint64_t ks64[((MAX_AES_NR) + 1) * (MAX_AES_NB)]; +#endif + uint32_t ks32[((MAX_AES_NR) + 1) * (MAX_AES_NB)]; +} aes_ks_t; + +/* aes_key.flags value: */ +#define INTEL_AES_NI_CAPABLE 0x1 /* AES-NI instructions present */ + +typedef struct aes_key aes_key_t; +struct aes_key { + aes_ks_t encr_ks; /* encryption key schedule */ + aes_ks_t decr_ks; /* decryption key schedule */ +#ifdef __amd64 + long double align128; /* Align fields above for Intel AES-NI */ + int flags; /* implementation-dependent flags */ +#endif /* __amd64 */ + int nr; /* number of rounds (10, 12, or 14) */ + int type; /* key schedule size (32 or 64 bits) */ +}; + +/* + * Core AES functions. + * ks and keysched are pointers to aes_key_t. + * They are declared void* as they are intended to be opaque types. + * Use function aes_alloc_keysched() to allocate memory for ks and keysched. + */ +extern void *aes_alloc_keysched(size_t *size, int kmflag); +extern void aes_init_keysched(const uint8_t *cipherKey, uint_t keyBits, + void *keysched); +extern int aes_encrypt_block(const void *ks, const uint8_t *pt, uint8_t *ct); +extern int aes_decrypt_block(const void *ks, const uint8_t *ct, uint8_t *pt); + +/* + * AES mode functions. + * The first 2 functions operate on 16-byte AES blocks. + */ +extern void aes_copy_block(uint8_t *in, uint8_t *out); +extern void aes_xor_block(uint8_t *data, uint8_t *dst); + +/* Note: ctx is a pointer to aes_ctx_t defined in modes.h */ +extern int aes_encrypt_contiguous_blocks(void *ctx, char *data, size_t length, + crypto_data_t *out); +extern int aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length, + crypto_data_t *out); + +/* + * The following definitions and declarations are only used by AES FIPS POST + */ +#ifdef _AES_IMPL + +typedef enum aes_mech_type { + AES_ECB_MECH_INFO_TYPE, /* SUN_CKM_AES_ECB */ + AES_CBC_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC */ + AES_CBC_PAD_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC_PAD */ + AES_CTR_MECH_INFO_TYPE, /* SUN_CKM_AES_CTR */ + AES_CCM_MECH_INFO_TYPE, /* SUN_CKM_AES_CCM */ + AES_GCM_MECH_INFO_TYPE, /* SUN_CKM_AES_GCM */ + AES_GMAC_MECH_INFO_TYPE /* SUN_CKM_AES_GMAC */ +} aes_mech_type_t; + +#endif /* _AES_IMPL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _AES_IMPL_H */ diff --git a/module/icp/include/modes/modes.h b/module/icp/include/modes/modes.h new file mode 100644 index 000000000..7c1f10b16 --- /dev/null +++ b/module/icp/include/modes/modes.h @@ -0,0 +1,385 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _COMMON_CRYPTO_MODES_H +#define _COMMON_CRYPTO_MODES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/zfs_context.h> +#include <sys/crypto/common.h> +#include <sys/crypto/impl.h> + +#define ECB_MODE 0x00000002 +#define CBC_MODE 0x00000004 +#define CTR_MODE 0x00000008 +#define CCM_MODE 0x00000010 +#define GCM_MODE 0x00000020 +#define GMAC_MODE 0x00000040 + +/* + * cc_keysched: Pointer to key schedule. + * + * cc_keysched_len: Length of the key schedule. + * + * cc_remainder: This is for residual data, i.e. data that can't + * be processed because there are too few bytes. + * Must wait until more data arrives. + * + * cc_remainder_len: Number of bytes in cc_remainder. + * + * cc_iv: Scratch buffer that sometimes contains the IV. + * + * cc_lastp: Pointer to previous block of ciphertext. + * + * cc_copy_to: Pointer to where encrypted residual data needs + * to be copied. + * + * cc_flags: PROVIDER_OWNS_KEY_SCHEDULE + * When a context is freed, it is necessary + * to know whether the key schedule was allocated + * by the caller, or internally, e.g. an init routine. + * If allocated by the latter, then it needs to be freed. + * + * ECB_MODE, CBC_MODE, CTR_MODE, or CCM_MODE + */ +struct common_ctx { + void *cc_keysched; + size_t cc_keysched_len; + uint64_t cc_iv[2]; + uint64_t cc_remainder[2]; + size_t cc_remainder_len; + uint8_t *cc_lastp; + uint8_t *cc_copy_to; + uint32_t cc_flags; +}; + +typedef struct common_ctx common_ctx_t; + +typedef struct ecb_ctx { + struct common_ctx ecb_common; + uint64_t ecb_lastblock[2]; +} ecb_ctx_t; + +#define ecb_keysched ecb_common.cc_keysched +#define ecb_keysched_len ecb_common.cc_keysched_len +#define ecb_iv ecb_common.cc_iv +#define ecb_remainder ecb_common.cc_remainder +#define ecb_remainder_len ecb_common.cc_remainder_len +#define ecb_lastp ecb_common.cc_lastp +#define ecb_copy_to ecb_common.cc_copy_to +#define ecb_flags ecb_common.cc_flags + +typedef struct cbc_ctx { + struct common_ctx cbc_common; + uint64_t cbc_lastblock[2]; +} cbc_ctx_t; + +#define cbc_keysched cbc_common.cc_keysched +#define cbc_keysched_len cbc_common.cc_keysched_len +#define cbc_iv cbc_common.cc_iv +#define cbc_remainder cbc_common.cc_remainder +#define cbc_remainder_len cbc_common.cc_remainder_len +#define cbc_lastp cbc_common.cc_lastp +#define cbc_copy_to cbc_common.cc_copy_to +#define cbc_flags cbc_common.cc_flags + +/* + * ctr_lower_mask Bit-mask for lower 8 bytes of counter block. + * ctr_upper_mask Bit-mask for upper 8 bytes of counter block. + */ +typedef struct ctr_ctx { + struct common_ctx ctr_common; + uint64_t ctr_lower_mask; + uint64_t ctr_upper_mask; + uint32_t ctr_tmp[4]; +} ctr_ctx_t; + +/* + * ctr_cb Counter block. + */ +#define ctr_keysched ctr_common.cc_keysched +#define ctr_keysched_len ctr_common.cc_keysched_len +#define ctr_cb ctr_common.cc_iv +#define ctr_remainder ctr_common.cc_remainder +#define ctr_remainder_len ctr_common.cc_remainder_len +#define ctr_lastp ctr_common.cc_lastp +#define ctr_copy_to ctr_common.cc_copy_to +#define ctr_flags ctr_common.cc_flags + +/* + * + * ccm_mac_len: Stores length of the MAC in CCM mode. + * ccm_mac_buf: Stores the intermediate value for MAC in CCM encrypt. + * In CCM decrypt, stores the input MAC value. + * ccm_data_len: Length of the plaintext for CCM mode encrypt, or + * length of the ciphertext for CCM mode decrypt. + * ccm_processed_data_len: + * Length of processed plaintext in CCM mode encrypt, + * or length of processed ciphertext for CCM mode decrypt. + * ccm_processed_mac_len: + * Length of MAC data accumulated in CCM mode decrypt. + * + * ccm_pt_buf: Only used in CCM mode decrypt. It stores the + * decrypted plaintext to be returned when + * MAC verification succeeds in decrypt_final. + * Memory for this should be allocated in the AES module. + * + */ +typedef struct ccm_ctx { + struct common_ctx ccm_common; + uint32_t ccm_tmp[4]; + size_t ccm_mac_len; + uint64_t ccm_mac_buf[2]; + size_t ccm_data_len; + size_t ccm_processed_data_len; + size_t ccm_processed_mac_len; + uint8_t *ccm_pt_buf; + uint64_t ccm_mac_input_buf[2]; + uint64_t ccm_counter_mask; +} ccm_ctx_t; + +#define ccm_keysched ccm_common.cc_keysched +#define ccm_keysched_len ccm_common.cc_keysched_len +#define ccm_cb ccm_common.cc_iv +#define ccm_remainder ccm_common.cc_remainder +#define ccm_remainder_len ccm_common.cc_remainder_len +#define ccm_lastp ccm_common.cc_lastp +#define ccm_copy_to ccm_common.cc_copy_to +#define ccm_flags ccm_common.cc_flags + +/* + * gcm_tag_len: Length of authentication tag. + * + * gcm_ghash: Stores output from the GHASH function. + * + * gcm_processed_data_len: + * Length of processed plaintext (encrypt) or + * length of processed ciphertext (decrypt). + * + * gcm_pt_buf: Stores the decrypted plaintext returned by + * decrypt_final when the computed authentication + * tag matches the user supplied tag. + * + * gcm_pt_buf_len: Length of the plaintext buffer. + * + * gcm_H: Subkey. + * + * gcm_J0: Pre-counter block generated from the IV. + * + * gcm_len_a_len_c: 64-bit representations of the bit lengths of + * AAD and ciphertext. + * + * gcm_kmflag: Current value of kmflag. Used only for allocating + * the plaintext buffer during decryption. + */ +typedef struct gcm_ctx { + struct common_ctx gcm_common; + size_t gcm_tag_len; + size_t gcm_processed_data_len; + size_t gcm_pt_buf_len; + uint32_t gcm_tmp[4]; + uint64_t gcm_ghash[2]; + uint64_t gcm_H[2]; + uint64_t gcm_J0[2]; + uint64_t gcm_len_a_len_c[2]; + uint8_t *gcm_pt_buf; + int gcm_kmflag; +} gcm_ctx_t; + +#define gcm_keysched gcm_common.cc_keysched +#define gcm_keysched_len gcm_common.cc_keysched_len +#define gcm_cb gcm_common.cc_iv +#define gcm_remainder gcm_common.cc_remainder +#define gcm_remainder_len gcm_common.cc_remainder_len +#define gcm_lastp gcm_common.cc_lastp +#define gcm_copy_to gcm_common.cc_copy_to +#define gcm_flags gcm_common.cc_flags + +#define AES_GMAC_IV_LEN 12 +#define AES_GMAC_TAG_BITS 128 + +typedef struct aes_ctx { + union { + ecb_ctx_t acu_ecb; + cbc_ctx_t acu_cbc; + ctr_ctx_t acu_ctr; + ccm_ctx_t acu_ccm; + gcm_ctx_t acu_gcm; + } acu; +} aes_ctx_t; + +#define ac_flags acu.acu_ecb.ecb_common.cc_flags +#define ac_remainder_len acu.acu_ecb.ecb_common.cc_remainder_len +#define ac_keysched acu.acu_ecb.ecb_common.cc_keysched +#define ac_keysched_len acu.acu_ecb.ecb_common.cc_keysched_len +#define ac_iv acu.acu_ecb.ecb_common.cc_iv +#define ac_lastp acu.acu_ecb.ecb_common.cc_lastp +#define ac_pt_buf acu.acu_ccm.ccm_pt_buf +#define ac_mac_len acu.acu_ccm.ccm_mac_len +#define ac_data_len acu.acu_ccm.ccm_data_len +#define ac_processed_mac_len acu.acu_ccm.ccm_processed_mac_len +#define ac_processed_data_len acu.acu_ccm.ccm_processed_data_len +#define ac_tag_len acu.acu_gcm.gcm_tag_len + +typedef struct blowfish_ctx { + union { + ecb_ctx_t bcu_ecb; + cbc_ctx_t bcu_cbc; + } bcu; +} blowfish_ctx_t; + +#define bc_flags bcu.bcu_ecb.ecb_common.cc_flags +#define bc_remainder_len bcu.bcu_ecb.ecb_common.cc_remainder_len +#define bc_keysched bcu.bcu_ecb.ecb_common.cc_keysched +#define bc_keysched_len bcu.bcu_ecb.ecb_common.cc_keysched_len +#define bc_iv bcu.bcu_ecb.ecb_common.cc_iv +#define bc_lastp bcu.bcu_ecb.ecb_common.cc_lastp + +typedef struct des_ctx { + union { + ecb_ctx_t dcu_ecb; + cbc_ctx_t dcu_cbc; + } dcu; +} des_ctx_t; + +#define dc_flags dcu.dcu_ecb.ecb_common.cc_flags +#define dc_remainder_len dcu.dcu_ecb.ecb_common.cc_remainder_len +#define dc_keysched dcu.dcu_ecb.ecb_common.cc_keysched +#define dc_keysched_len dcu.dcu_ecb.ecb_common.cc_keysched_len +#define dc_iv dcu.dcu_ecb.ecb_common.cc_iv +#define dc_lastp dcu.dcu_ecb.ecb_common.cc_lastp + +extern int ecb_cipher_contiguous_blocks(ecb_ctx_t *, char *, size_t, + crypto_data_t *, size_t, int (*cipher)(const void *, const uint8_t *, + uint8_t *)); + +extern int cbc_encrypt_contiguous_blocks(cbc_ctx_t *, char *, size_t, + crypto_data_t *, size_t, + int (*encrypt)(const void *, const uint8_t *, uint8_t *), + void (*copy_block)(uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int cbc_decrypt_contiguous_blocks(cbc_ctx_t *, char *, size_t, + crypto_data_t *, size_t, + int (*decrypt)(const void *, const uint8_t *, uint8_t *), + void (*copy_block)(uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int ctr_mode_contiguous_blocks(ctr_ctx_t *, char *, size_t, + crypto_data_t *, size_t, + int (*cipher)(const void *, const uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int ccm_mode_encrypt_contiguous_blocks(ccm_ctx_t *, char *, size_t, + crypto_data_t *, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*copy_block)(uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int ccm_mode_decrypt_contiguous_blocks(ccm_ctx_t *, char *, size_t, + crypto_data_t *, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*copy_block)(uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int gcm_mode_encrypt_contiguous_blocks(gcm_ctx_t *, char *, size_t, + crypto_data_t *, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*copy_block)(uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int gcm_mode_decrypt_contiguous_blocks(gcm_ctx_t *, char *, size_t, + crypto_data_t *, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*copy_block)(uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +int ccm_encrypt_final(ccm_ctx_t *, crypto_data_t *, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +int gcm_encrypt_final(gcm_ctx_t *, crypto_data_t *, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*copy_block)(uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int ccm_decrypt_final(ccm_ctx_t *, crypto_data_t *, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*copy_block)(uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int gcm_decrypt_final(gcm_ctx_t *, crypto_data_t *, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int ctr_mode_final(ctr_ctx_t *, crypto_data_t *, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *)); + +extern int cbc_init_ctx(cbc_ctx_t *, char *, size_t, size_t, + void (*copy_block)(uint8_t *, uint64_t *)); + +extern int ctr_init_ctx(ctr_ctx_t *, ulong_t, uint8_t *, + void (*copy_block)(uint8_t *, uint8_t *)); + +extern int ccm_init_ctx(ccm_ctx_t *, char *, int, boolean_t, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int gcm_init_ctx(gcm_ctx_t *, char *, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*copy_block)(uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern int gmac_init_ctx(gcm_ctx_t *, char *, size_t, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), + void (*copy_block)(uint8_t *, uint8_t *), + void (*xor_block)(uint8_t *, uint8_t *)); + +extern void calculate_ccm_mac(ccm_ctx_t *, uint8_t *, + int (*encrypt_block)(const void *, const uint8_t *, uint8_t *)); + +extern void gcm_mul(uint64_t *, uint64_t *, uint64_t *); + +extern void crypto_init_ptrs(crypto_data_t *, void **, offset_t *); +extern void crypto_get_ptrs(crypto_data_t *, void **, offset_t *, + uint8_t **, size_t *, uint8_t **, size_t); + +extern void *ecb_alloc_ctx(int); +extern void *cbc_alloc_ctx(int); +extern void *ctr_alloc_ctx(int); +extern void *ccm_alloc_ctx(int); +extern void *gcm_alloc_ctx(int); +extern void *gmac_alloc_ctx(int); +extern void crypto_free_mode_ctx(void *); +extern void gcm_set_kmflag(gcm_ctx_t *, int); + +#ifdef __cplusplus +} +#endif + +#endif /* _COMMON_CRYPTO_MODES_H */ diff --git a/module/icp/include/sha1/sha1.h b/module/icp/include/sha1/sha1.h new file mode 100644 index 000000000..b6ae6b8d2 --- /dev/null +++ b/module/icp/include/sha1/sha1.h @@ -0,0 +1,61 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_SHA1_H +#define _SYS_SHA1_H + +#include <sys/types.h> /* for uint_* */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * NOTE: n2rng (Niagara2 RNG driver) accesses the state field of + * SHA1_CTX directly. NEVER change this structure without verifying + * compatiblity with n2rng. The important thing is that the state + * must be in a field declared as uint32_t state[5]. + */ +/* SHA-1 context. */ +typedef struct { + uint32_t state[5]; /* state (ABCDE) */ + uint32_t count[2]; /* number of bits, modulo 2^64 (msb first) */ + union { + uint8_t buf8[64]; /* undigested input */ + uint32_t buf32[16]; /* realigned input */ + } buf_un; +} SHA1_CTX; + +#define SHA1_DIGEST_LENGTH 20 + +void SHA1Init(SHA1_CTX *); +void SHA1Update(SHA1_CTX *, const void *, size_t); +void SHA1Final(void *, SHA1_CTX *); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SHA1_H */ diff --git a/module/icp/include/sha1/sha1_consts.h b/module/icp/include/sha1/sha1_consts.h new file mode 100644 index 000000000..848d25ef0 --- /dev/null +++ b/module/icp/include/sha1/sha1_consts.h @@ -0,0 +1,65 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1998, by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _SYS_SHA1_CONSTS_H +#define _SYS_SHA1_CONSTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * as explained in sha1.c, loading 32-bit constants on a sparc is expensive + * since it involves both a `sethi' and an `or'. thus, we instead use `ld' + * to load the constants from an array called `sha1_consts'. however, on + * intel (and perhaps other processors), it is cheaper to load the constant + * directly. thus, the c code in SHA1Transform() uses the macro SHA1_CONST() + * which either expands to a constant or an array reference, depending on + * the architecture the code is being compiled for. + */ + +#include <sys/types.h> /* uint32_t */ + +extern const uint32_t sha1_consts[]; + +#if defined(__sparc) +#define SHA1_CONST(x) (sha1_consts[x]) +#else +#define SHA1_CONST(x) (SHA1_CONST_ ## x) +#endif + +/* constants, as provided in FIPS 180-1 */ + +#define SHA1_CONST_0 0x5a827999U +#define SHA1_CONST_1 0x6ed9eba1U +#define SHA1_CONST_2 0x8f1bbcdcU +#define SHA1_CONST_3 0xca62c1d6U + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SHA1_CONSTS_H */ diff --git a/module/icp/include/sha1/sha1_impl.h b/module/icp/include/sha1/sha1_impl.h new file mode 100644 index 000000000..1c1f8728f --- /dev/null +++ b/module/icp/include/sha1/sha1_impl.h @@ -0,0 +1,73 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SHA1_IMPL_H +#define _SHA1_IMPL_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#define SHA1_HASH_SIZE 20 /* SHA_1 digest length in bytes */ +#define SHA1_DIGEST_LENGTH 20 /* SHA1 digest length in bytes */ +#define SHA1_HMAC_BLOCK_SIZE 64 /* SHA1-HMAC block size */ +#define SHA1_HMAC_MIN_KEY_LEN 1 /* SHA1-HMAC min key length in bytes */ +#define SHA1_HMAC_MAX_KEY_LEN INT_MAX /* SHA1-HMAC max key length in bytes */ +#define SHA1_HMAC_INTS_PER_BLOCK (SHA1_HMAC_BLOCK_SIZE/sizeof (uint32_t)) + +/* + * CSPI information (entry points, provider info, etc.) + */ +typedef enum sha1_mech_type { + SHA1_MECH_INFO_TYPE, /* SUN_CKM_SHA1 */ + SHA1_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA1_HMAC */ + SHA1_HMAC_GEN_MECH_INFO_TYPE /* SUN_CKM_SHA1_HMAC_GENERAL */ +} sha1_mech_type_t; + +/* + * Context for SHA1 mechanism. + */ +typedef struct sha1_ctx { + sha1_mech_type_t sc_mech_type; /* type of context */ + SHA1_CTX sc_sha1_ctx; /* SHA1 context */ +} sha1_ctx_t; + +/* + * Context for SHA1-HMAC and SHA1-HMAC-GENERAL mechanisms. + */ +typedef struct sha1_hmac_ctx { + sha1_mech_type_t hc_mech_type; /* type of context */ + uint32_t hc_digest_len; /* digest len in bytes */ + SHA1_CTX hc_icontext; /* inner SHA1 context */ + SHA1_CTX hc_ocontext; /* outer SHA1 context */ +} sha1_hmac_ctx_t; + + +#ifdef __cplusplus +} +#endif + +#endif /* _SHA1_IMPL_H */ diff --git a/module/icp/include/sha2/sha2.h b/module/icp/include/sha2/sha2.h new file mode 100644 index 000000000..8e53987a7 --- /dev/null +++ b/module/icp/include/sha2/sha2.h @@ -0,0 +1,116 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* Copyright 2013 Saso Kiselkov. All rights reserved. */ + +#ifndef _SYS_SHA2_H +#define _SYS_SHA2_H + +#include <sys/types.h> /* for uint_* */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SHA2_HMAC_MIN_KEY_LEN 1 /* SHA2-HMAC min key length in bytes */ +#define SHA2_HMAC_MAX_KEY_LEN INT_MAX /* SHA2-HMAC max key length in bytes */ + +#define SHA256_DIGEST_LENGTH 32 /* SHA256 digest length in bytes */ + +#define SHA256_HMAC_BLOCK_SIZE 64 /* SHA256-HMAC block size */ + +#define SHA256 0 +#define SHA256_HMAC 1 +#define SHA256_HMAC_GEN 2 + +/* + * SHA2 context. + * The contents of this structure are a private interface between the + * Init/Update/Final calls of the functions defined below. + * Callers must never attempt to read or write any of the fields + * in this structure directly. + */ +typedef struct { + uint32_t algotype; /* Algorithm Type */ + + /* state (ABCDEFGH) */ + union { + uint32_t s32[8]; /* for SHA256 */ + uint64_t s64[8]; /* for SHA384/512 */ + } state; + /* number of bits */ + union { + uint32_t c32[2]; /* for SHA256 , modulo 2^64 */ + uint64_t c64[2]; /* for SHA384/512, modulo 2^128 */ + } count; + union { + uint8_t buf8[128]; /* undigested input */ + uint32_t buf32[32]; /* realigned input */ + uint64_t buf64[16]; /* realigned input */ + } buf_un; +} SHA2_CTX; + +typedef SHA2_CTX SHA256_CTX; +typedef SHA2_CTX SHA384_CTX; +typedef SHA2_CTX SHA512_CTX; + +extern void SHA2Init(uint64_t mech, SHA2_CTX *); + +extern void SHA2Update(SHA2_CTX *, const void *, size_t); + +extern void SHA2Final(void *, SHA2_CTX *); + +extern void SHA256Init(SHA256_CTX *); + +extern void SHA256Update(SHA256_CTX *, const void *, size_t); + +extern void SHA256Final(void *, SHA256_CTX *); + +#ifdef _SHA2_IMPL +/* + * The following types/functions are all private to the implementation + * of the SHA2 functions and must not be used by consumers of the interface + */ + +/* + * List of support mechanisms in this module. + * + * It is important to note that in the module, division or modulus calculations + * are used on the enumerated type to determine which mechanism is being used; + * therefore, changing the order or additional mechanisms should be done + * carefully + */ +typedef enum sha2_mech_type { + SHA256_MECH_INFO_TYPE, /* SUN_CKM_SHA256 */ + SHA256_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC */ + SHA256_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC_GENERAL */ +} sha2_mech_type_t; + +#endif /* _SHA2_IMPL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SHA2_H */ diff --git a/module/icp/include/sha2/sha2_consts.h b/module/icp/include/sha2/sha2_consts.h new file mode 100644 index 000000000..3a6645508 --- /dev/null +++ b/module/icp/include/sha2/sha2_consts.h @@ -0,0 +1,219 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_SHA2_CONSTS_H +#define _SYS_SHA2_CONSTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Loading 32-bit constants on a sparc is expensive since it involves both + * a `sethi' and an `or'. thus, we instead use `ld' to load the constants + * from an array called `sha2_consts'. however, on intel (and perhaps other + * processors), it is cheaper to load the constant directly. thus, the c + * code in SHA transform functions uses the macro SHA2_CONST() which either + * expands to a constant or an array reference, depending on + * the architecture the code is being compiled for. + * + * SHA512 constants are used for SHA384 + */ + +#include <sys/types.h> /* uint32_t */ + +extern const uint32_t sha256_consts[]; +extern const uint64_t sha512_consts[]; + +#if defined(__sparc) +#define SHA256_CONST(x) (sha256_consts[x]) +#define SHA512_CONST(x) (sha512_consts[x]) +#else +#define SHA256_CONST(x) (SHA256_CONST_ ## x) +#define SHA512_CONST(x) (SHA512_CONST_ ## x) +#endif + +/* constants, as provided in FIPS 180-2 */ + +#define SHA256_CONST_0 0x428a2f98U +#define SHA256_CONST_1 0x71374491U +#define SHA256_CONST_2 0xb5c0fbcfU +#define SHA256_CONST_3 0xe9b5dba5U +#define SHA256_CONST_4 0x3956c25bU +#define SHA256_CONST_5 0x59f111f1U +#define SHA256_CONST_6 0x923f82a4U +#define SHA256_CONST_7 0xab1c5ed5U + +#define SHA256_CONST_8 0xd807aa98U +#define SHA256_CONST_9 0x12835b01U +#define SHA256_CONST_10 0x243185beU +#define SHA256_CONST_11 0x550c7dc3U +#define SHA256_CONST_12 0x72be5d74U +#define SHA256_CONST_13 0x80deb1feU +#define SHA256_CONST_14 0x9bdc06a7U +#define SHA256_CONST_15 0xc19bf174U + +#define SHA256_CONST_16 0xe49b69c1U +#define SHA256_CONST_17 0xefbe4786U +#define SHA256_CONST_18 0x0fc19dc6U +#define SHA256_CONST_19 0x240ca1ccU +#define SHA256_CONST_20 0x2de92c6fU +#define SHA256_CONST_21 0x4a7484aaU +#define SHA256_CONST_22 0x5cb0a9dcU +#define SHA256_CONST_23 0x76f988daU + +#define SHA256_CONST_24 0x983e5152U +#define SHA256_CONST_25 0xa831c66dU +#define SHA256_CONST_26 0xb00327c8U +#define SHA256_CONST_27 0xbf597fc7U +#define SHA256_CONST_28 0xc6e00bf3U +#define SHA256_CONST_29 0xd5a79147U +#define SHA256_CONST_30 0x06ca6351U +#define SHA256_CONST_31 0x14292967U + +#define SHA256_CONST_32 0x27b70a85U +#define SHA256_CONST_33 0x2e1b2138U +#define SHA256_CONST_34 0x4d2c6dfcU +#define SHA256_CONST_35 0x53380d13U +#define SHA256_CONST_36 0x650a7354U +#define SHA256_CONST_37 0x766a0abbU +#define SHA256_CONST_38 0x81c2c92eU +#define SHA256_CONST_39 0x92722c85U + +#define SHA256_CONST_40 0xa2bfe8a1U +#define SHA256_CONST_41 0xa81a664bU +#define SHA256_CONST_42 0xc24b8b70U +#define SHA256_CONST_43 0xc76c51a3U +#define SHA256_CONST_44 0xd192e819U +#define SHA256_CONST_45 0xd6990624U +#define SHA256_CONST_46 0xf40e3585U +#define SHA256_CONST_47 0x106aa070U + +#define SHA256_CONST_48 0x19a4c116U +#define SHA256_CONST_49 0x1e376c08U +#define SHA256_CONST_50 0x2748774cU +#define SHA256_CONST_51 0x34b0bcb5U +#define SHA256_CONST_52 0x391c0cb3U +#define SHA256_CONST_53 0x4ed8aa4aU +#define SHA256_CONST_54 0x5b9cca4fU +#define SHA256_CONST_55 0x682e6ff3U + +#define SHA256_CONST_56 0x748f82eeU +#define SHA256_CONST_57 0x78a5636fU +#define SHA256_CONST_58 0x84c87814U +#define SHA256_CONST_59 0x8cc70208U +#define SHA256_CONST_60 0x90befffaU +#define SHA256_CONST_61 0xa4506cebU +#define SHA256_CONST_62 0xbef9a3f7U +#define SHA256_CONST_63 0xc67178f2U + +#define SHA512_CONST_0 0x428a2f98d728ae22ULL +#define SHA512_CONST_1 0x7137449123ef65cdULL +#define SHA512_CONST_2 0xb5c0fbcfec4d3b2fULL +#define SHA512_CONST_3 0xe9b5dba58189dbbcULL +#define SHA512_CONST_4 0x3956c25bf348b538ULL +#define SHA512_CONST_5 0x59f111f1b605d019ULL +#define SHA512_CONST_6 0x923f82a4af194f9bULL +#define SHA512_CONST_7 0xab1c5ed5da6d8118ULL +#define SHA512_CONST_8 0xd807aa98a3030242ULL +#define SHA512_CONST_9 0x12835b0145706fbeULL +#define SHA512_CONST_10 0x243185be4ee4b28cULL +#define SHA512_CONST_11 0x550c7dc3d5ffb4e2ULL +#define SHA512_CONST_12 0x72be5d74f27b896fULL +#define SHA512_CONST_13 0x80deb1fe3b1696b1ULL +#define SHA512_CONST_14 0x9bdc06a725c71235ULL +#define SHA512_CONST_15 0xc19bf174cf692694ULL +#define SHA512_CONST_16 0xe49b69c19ef14ad2ULL +#define SHA512_CONST_17 0xefbe4786384f25e3ULL +#define SHA512_CONST_18 0x0fc19dc68b8cd5b5ULL +#define SHA512_CONST_19 0x240ca1cc77ac9c65ULL +#define SHA512_CONST_20 0x2de92c6f592b0275ULL +#define SHA512_CONST_21 0x4a7484aa6ea6e483ULL +#define SHA512_CONST_22 0x5cb0a9dcbd41fbd4ULL +#define SHA512_CONST_23 0x76f988da831153b5ULL +#define SHA512_CONST_24 0x983e5152ee66dfabULL +#define SHA512_CONST_25 0xa831c66d2db43210ULL +#define SHA512_CONST_26 0xb00327c898fb213fULL +#define SHA512_CONST_27 0xbf597fc7beef0ee4ULL +#define SHA512_CONST_28 0xc6e00bf33da88fc2ULL +#define SHA512_CONST_29 0xd5a79147930aa725ULL +#define SHA512_CONST_30 0x06ca6351e003826fULL +#define SHA512_CONST_31 0x142929670a0e6e70ULL +#define SHA512_CONST_32 0x27b70a8546d22ffcULL +#define SHA512_CONST_33 0x2e1b21385c26c926ULL +#define SHA512_CONST_34 0x4d2c6dfc5ac42aedULL +#define SHA512_CONST_35 0x53380d139d95b3dfULL +#define SHA512_CONST_36 0x650a73548baf63deULL +#define SHA512_CONST_37 0x766a0abb3c77b2a8ULL +#define SHA512_CONST_38 0x81c2c92e47edaee6ULL +#define SHA512_CONST_39 0x92722c851482353bULL +#define SHA512_CONST_40 0xa2bfe8a14cf10364ULL +#define SHA512_CONST_41 0xa81a664bbc423001ULL +#define SHA512_CONST_42 0xc24b8b70d0f89791ULL +#define SHA512_CONST_43 0xc76c51a30654be30ULL +#define SHA512_CONST_44 0xd192e819d6ef5218ULL +#define SHA512_CONST_45 0xd69906245565a910ULL +#define SHA512_CONST_46 0xf40e35855771202aULL +#define SHA512_CONST_47 0x106aa07032bbd1b8ULL +#define SHA512_CONST_48 0x19a4c116b8d2d0c8ULL +#define SHA512_CONST_49 0x1e376c085141ab53ULL +#define SHA512_CONST_50 0x2748774cdf8eeb99ULL +#define SHA512_CONST_51 0x34b0bcb5e19b48a8ULL +#define SHA512_CONST_52 0x391c0cb3c5c95a63ULL +#define SHA512_CONST_53 0x4ed8aa4ae3418acbULL +#define SHA512_CONST_54 0x5b9cca4f7763e373ULL +#define SHA512_CONST_55 0x682e6ff3d6b2b8a3ULL +#define SHA512_CONST_56 0x748f82ee5defb2fcULL +#define SHA512_CONST_57 0x78a5636f43172f60ULL +#define SHA512_CONST_58 0x84c87814a1f0ab72ULL +#define SHA512_CONST_59 0x8cc702081a6439ecULL +#define SHA512_CONST_60 0x90befffa23631e28ULL +#define SHA512_CONST_61 0xa4506cebde82bde9ULL +#define SHA512_CONST_62 0xbef9a3f7b2c67915ULL +#define SHA512_CONST_63 0xc67178f2e372532bULL +#define SHA512_CONST_64 0xca273eceea26619cULL +#define SHA512_CONST_65 0xd186b8c721c0c207ULL +#define SHA512_CONST_66 0xeada7dd6cde0eb1eULL +#define SHA512_CONST_67 0xf57d4f7fee6ed178ULL +#define SHA512_CONST_68 0x06f067aa72176fbaULL +#define SHA512_CONST_69 0x0a637dc5a2c898a6ULL +#define SHA512_CONST_70 0x113f9804bef90daeULL +#define SHA512_CONST_71 0x1b710b35131c471bULL +#define SHA512_CONST_72 0x28db77f523047d84ULL +#define SHA512_CONST_73 0x32caab7b40c72493ULL +#define SHA512_CONST_74 0x3c9ebe0a15c9bebcULL +#define SHA512_CONST_75 0x431d67c49c100d4cULL +#define SHA512_CONST_76 0x4cc5d4becb3e42b6ULL +#define SHA512_CONST_77 0x597f299cfc657e2aULL +#define SHA512_CONST_78 0x5fcb6fab3ad6faecULL +#define SHA512_CONST_79 0x6c44198c4a475817ULL + + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SHA2_CONSTS_H */ diff --git a/module/icp/include/sha2/sha2_impl.h b/module/icp/include/sha2/sha2_impl.h new file mode 100644 index 000000000..bb42c3cd4 --- /dev/null +++ b/module/icp/include/sha2/sha2_impl.h @@ -0,0 +1,62 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SHA2_IMPL_H +#define _SHA2_IMPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SHA1_TYPE, + SHA256_TYPE, + SHA384_TYPE, + SHA512_TYPE +} sha2_mech_t; + +/* + * Context for SHA2 mechanism. + */ +typedef struct sha2_ctx { + sha2_mech_type_t sc_mech_type; /* type of context */ + SHA2_CTX sc_sha2_ctx; /* SHA2 context */ +} sha2_ctx_t; + +/* + * Context for SHA2 HMAC and HMAC GENERAL mechanisms. + */ +typedef struct sha2_hmac_ctx { + sha2_mech_type_t hc_mech_type; /* type of context */ + uint32_t hc_digest_len; /* digest len in bytes */ + SHA2_CTX hc_icontext; /* inner SHA2 context */ + SHA2_CTX hc_ocontext; /* outer SHA2 context */ +} sha2_hmac_ctx_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _SHA2_IMPL_H */ diff --git a/module/icp/include/sys/asm_linkage.h b/module/icp/include/sys/asm_linkage.h new file mode 100644 index 000000000..380597857 --- /dev/null +++ b/module/icp/include/sys/asm_linkage.h @@ -0,0 +1,36 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_ASM_LINKAGE_H +#define _SYS_ASM_LINKAGE_H + +#if defined(__i386) || defined(__amd64) + +#include <sys/ia32/asm_linkage.h> /* XX64 x86/sys/asm_linkage.h */ + +#endif + +#endif /* _SYS_ASM_LINKAGE_H */ diff --git a/module/icp/include/sys/bitmap.h b/module/icp/include/sys/bitmap.h new file mode 100644 index 000000000..b1f6823e6 --- /dev/null +++ b/module/icp/include/sys/bitmap.h @@ -0,0 +1,183 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +#ifndef _SYS_BITMAP_H +#define _SYS_BITMAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__GNUC__) && defined(_ASM_INLINES) && \ + (defined(__i386) || defined(__amd64)) +#include <asm/bitmap.h> +#endif + +/* + * Operations on bitmaps of arbitrary size + * A bitmap is a vector of 1 or more ulong_t's. + * The user of the package is responsible for range checks and keeping + * track of sizes. + */ + +#ifdef _LP64 +#define BT_ULSHIFT 6 /* log base 2 of BT_NBIPUL, to extract word index */ +#define BT_ULSHIFT32 5 /* log base 2 of BT_NBIPUL, to extract word index */ +#else +#define BT_ULSHIFT 5 /* log base 2 of BT_NBIPUL, to extract word index */ +#endif + +#define BT_NBIPUL (1 << BT_ULSHIFT) /* n bits per ulong_t */ +#define BT_ULMASK (BT_NBIPUL - 1) /* to extract bit index */ + +#ifdef _LP64 +#define BT_NBIPUL32 (1 << BT_ULSHIFT32) /* n bits per ulong_t */ +#define BT_ULMASK32 (BT_NBIPUL32 - 1) /* to extract bit index */ +#define BT_ULMAXMASK 0xffffffffffffffff /* used by bt_getlowbit */ +#else +#define BT_ULMAXMASK 0xffffffff +#endif + +/* + * bitmap is a ulong_t *, bitindex an index_t + * + * The macros BT_WIM and BT_BIW internal; there is no need + * for users of this package to use them. + */ + +/* + * word in map + */ +#define BT_WIM(bitmap, bitindex) \ + ((bitmap)[(bitindex) >> BT_ULSHIFT]) +/* + * bit in word + */ +#define BT_BIW(bitindex) \ + (1UL << ((bitindex) & BT_ULMASK)) + +#ifdef _LP64 +#define BT_WIM32(bitmap, bitindex) \ + ((bitmap)[(bitindex) >> BT_ULSHIFT32]) + +#define BT_BIW32(bitindex) \ + (1UL << ((bitindex) & BT_ULMASK32)) +#endif + +/* + * These are public macros + * + * BT_BITOUL == n bits to n ulong_t's + */ +#define BT_BITOUL(nbits) \ + (((nbits) + BT_NBIPUL - 1l) / BT_NBIPUL) +#define BT_SIZEOFMAP(nbits) \ + (BT_BITOUL(nbits) * sizeof (ulong_t)) +#define BT_TEST(bitmap, bitindex) \ + ((BT_WIM((bitmap), (bitindex)) & BT_BIW(bitindex)) ? 1 : 0) +#define BT_SET(bitmap, bitindex) \ + { BT_WIM((bitmap), (bitindex)) |= BT_BIW(bitindex); } +#define BT_CLEAR(bitmap, bitindex) \ + { BT_WIM((bitmap), (bitindex)) &= ~BT_BIW(bitindex); } + +#ifdef _LP64 +#define BT_BITOUL32(nbits) \ + (((nbits) + BT_NBIPUL32 - 1l) / BT_NBIPUL32) +#define BT_SIZEOFMAP32(nbits) \ + (BT_BITOUL32(nbits) * sizeof (uint_t)) +#define BT_TEST32(bitmap, bitindex) \ + ((BT_WIM32((bitmap), (bitindex)) & BT_BIW32(bitindex)) ? 1 : 0) +#define BT_SET32(bitmap, bitindex) \ + { BT_WIM32((bitmap), (bitindex)) |= BT_BIW32(bitindex); } +#define BT_CLEAR32(bitmap, bitindex) \ + { BT_WIM32((bitmap), (bitindex)) &= ~BT_BIW32(bitindex); } +#endif /* _LP64 */ + + +/* + * BIT_ONLYONESET is a private macro not designed for bitmaps of + * arbitrary size. u must be an unsigned integer/long. It returns + * true if one and only one bit is set in u. + */ +#define BIT_ONLYONESET(u) \ + ((((u) == 0) ? 0 : ((u) & ((u) - 1)) == 0)) + +#ifndef _ASM + +/* + * return next available bit index from map with specified number of bits + */ +extern index_t bt_availbit(ulong_t *bitmap, size_t nbits); +/* + * find the highest order bit that is on, and is within or below + * the word specified by wx + */ +extern int bt_gethighbit(ulong_t *mapp, int wx); +extern int bt_range(ulong_t *bitmap, size_t *pos1, size_t *pos2, + size_t end_pos); +extern int bt_getlowbit(ulong_t *bitmap, size_t start, size_t stop); +extern void bt_copy(ulong_t *, ulong_t *, ulong_t); + +/* + * find the parity + */ +extern int odd_parity(ulong_t); + +/* + * Atomically set/clear bits + * Atomic exclusive operations will set "result" to "-1" + * if the bit is already set/cleared. "result" will be set + * to 0 otherwise. + */ +#define BT_ATOMIC_SET(bitmap, bitindex) \ + { atomic_or_long(&(BT_WIM(bitmap, bitindex)), BT_BIW(bitindex)); } +#define BT_ATOMIC_CLEAR(bitmap, bitindex) \ + { atomic_and_long(&(BT_WIM(bitmap, bitindex)), ~BT_BIW(bitindex)); } + +#define BT_ATOMIC_SET_EXCL(bitmap, bitindex, result) \ + { result = atomic_set_long_excl(&(BT_WIM(bitmap, bitindex)), \ + (bitindex) % BT_NBIPUL); } +#define BT_ATOMIC_CLEAR_EXCL(bitmap, bitindex, result) \ + { result = atomic_clear_long_excl(&(BT_WIM(bitmap, bitindex)), \ + (bitindex) % BT_NBIPUL); } + +/* + * Extracts bits between index h (high, inclusive) and l (low, exclusive) from + * u, which must be an unsigned integer. + */ +#define BITX(u, h, l) (((u) >> (l)) & ((1LU << ((h) - (l) + 1LU)) - 1LU)) + +#endif /* _ASM */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_BITMAP_H */ diff --git a/module/icp/include/sys/crypto/elfsign.h b/module/icp/include/sys/crypto/elfsign.h new file mode 100644 index 000000000..5432f0c8d --- /dev/null +++ b/module/icp/include/sys/crypto/elfsign.h @@ -0,0 +1,137 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_CRYPTO_ELFSIGN_H +#define _SYS_CRYPTO_ELFSIGN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Consolidation Private Interface for elfsign/libpkcs11/kcfd + */ + +#include <sys/zfs_context.h> + +/* + * Project Private structures and types used for communication between kcfd + * and KCF over the door. + */ + +typedef enum ELFsign_status_e { + ELFSIGN_UNKNOWN, + ELFSIGN_SUCCESS, + ELFSIGN_FAILED, + ELFSIGN_NOTSIGNED, + ELFSIGN_INVALID_CERTPATH, + ELFSIGN_INVALID_ELFOBJ, + ELFSIGN_RESTRICTED +} ELFsign_status_t; + +#define KCF_KCFD_VERSION1 1 +#define SIG_MAX_LENGTH 1024 + +#define ELF_SIGNATURE_SECTION ".SUNW_signature" + +typedef struct kcf_door_arg_s { + short da_version; + boolean_t da_iskernel; + + union { + char filename[MAXPATHLEN]; /* For request */ + + struct kcf_door_result_s { /* For response */ + ELFsign_status_t status; + uint32_t siglen; + uchar_t signature[1]; + } result; + } da_u; +} kcf_door_arg_t; + +typedef uint32_t filesig_vers_t; + +/* + * File Signature Structure + * Applicable to ELF and other file formats + */ +struct filesignatures { + uint32_t filesig_cnt; /* count of signatures */ + uint32_t filesig_pad; /* unused */ + union { + char filesig_data[1]; + struct filesig { /* one of these for each signature */ + uint32_t filesig_size; + filesig_vers_t filesig_version; + union { + struct filesig_version1 { + uint32_t filesig_v1_dnsize; + uint32_t filesig_v1_sigsize; + uint32_t filesig_v1_oidsize; + char filesig_v1_data[1]; + } filesig_v1; + struct filesig_version3 { + uint64_t filesig_v3_time; + uint32_t filesig_v3_dnsize; + uint32_t filesig_v3_sigsize; + uint32_t filesig_v3_oidsize; + char filesig_v3_data[1]; + } filesig_v3; + } _u2; + } filesig_sig; + uint64_t filesig_align; + } _u1; +}; +#define filesig_sig _u1.filesig_sig + +#define filesig_v1_dnsize _u2.filesig_v1.filesig_v1_dnsize +#define filesig_v1_sigsize _u2.filesig_v1.filesig_v1_sigsize +#define filesig_v1_oidsize _u2.filesig_v1.filesig_v1_oidsize +#define filesig_v1_data _u2.filesig_v1.filesig_v1_data + +#define filesig_v3_time _u2.filesig_v3.filesig_v3_time +#define filesig_v3_dnsize _u2.filesig_v3.filesig_v3_dnsize +#define filesig_v3_sigsize _u2.filesig_v3.filesig_v3_sigsize +#define filesig_v3_oidsize _u2.filesig_v3.filesig_v3_oidsize +#define filesig_v3_data _u2.filesig_v3.filesig_v3_data + +#define filesig_ALIGN(s) (((s) + sizeof (uint64_t) - 1) & \ + (-sizeof (uint64_t))) +#define filesig_next(ptr) (struct filesig *)((void *)((char *)(ptr) + \ + filesig_ALIGN((ptr)->filesig_size))) + +#define FILESIG_UNKNOWN 0 /* unrecognized version */ +#define FILESIG_VERSION1 1 /* version1, all but sig section */ +#define FILESIG_VERSION2 2 /* version1 format, SHF_ALLOC only */ +#define FILESIG_VERSION3 3 /* version3, all but sig section */ +#define FILESIG_VERSION4 4 /* version3 format, SHF_ALLOC only */ + +#define _PATH_KCFD_DOOR "/etc/svc/volatile/kcfd_door" + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_CRYPTO_ELFSIGN_H */ diff --git a/module/icp/include/sys/crypto/impl.h b/module/icp/include/sys/crypto/impl.h new file mode 100644 index 000000000..6d8ea8d65 --- /dev/null +++ b/module/icp/include/sys/crypto/impl.h @@ -0,0 +1,1370 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_CRYPTO_IMPL_H +#define _SYS_CRYPTO_IMPL_H + +/* + * Kernel Cryptographic Framework private implementation definitions. + */ + +#include <sys/zfs_context.h> +#include <sys/crypto/common.h> +#include <sys/crypto/api.h> +#include <sys/crypto/spi.h> +#include <sys/crypto/ioctl.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define KCF_MODULE "kcf" + +/* + * Prefixes convention: structures internal to the kernel cryptographic + * framework start with 'kcf_'. Exposed structure start with 'crypto_'. + */ + +/* Provider stats. Not protected. */ +typedef struct kcf_prov_stats { + kstat_named_t ps_ops_total; + kstat_named_t ps_ops_passed; + kstat_named_t ps_ops_failed; + kstat_named_t ps_ops_busy_rval; +} kcf_prov_stats_t; + +/* Various kcf stats. Not protected. */ +typedef struct kcf_stats { + kstat_named_t ks_thrs_in_pool; + kstat_named_t ks_idle_thrs; + kstat_named_t ks_minthrs; + kstat_named_t ks_maxthrs; + kstat_named_t ks_swq_njobs; + kstat_named_t ks_swq_maxjobs; + kstat_named_t ks_taskq_threads; + kstat_named_t ks_taskq_minalloc; + kstat_named_t ks_taskq_maxalloc; +} kcf_stats_t; + +/* + * Keep all the information needed by the scheduler from + * this provider. + */ +typedef struct kcf_sched_info { + /* The number of operations dispatched. */ + uint64_t ks_ndispatches; + + /* The number of operations that failed. */ + uint64_t ks_nfails; + + /* The number of operations that returned CRYPTO_BUSY. */ + uint64_t ks_nbusy_rval; + + /* taskq used to dispatch crypto requests */ + taskq_t *ks_taskq; +} kcf_sched_info_t; + +/* + * pd_irefcnt approximates the number of inflight requests to the + * provider. Though we increment this counter during registration for + * other purposes, that base value is mostly same across all providers. + * So, it is a good measure of the load on a provider when it is not + * in a busy state. Once a provider notifies it is busy, requests + * backup in the taskq. So, we use tq_nalloc in that case which gives + * the number of task entries in the task queue. Note that we do not + * acquire any locks here as it is not critical to get the exact number + * and the lock contention may be too costly for this code path. + */ +#define KCF_PROV_LOAD(pd) ((pd)->pd_state != KCF_PROV_BUSY ? \ + (pd)->pd_irefcnt : (pd)->pd_sched_info.ks_taskq->tq_nalloc) + +#define KCF_PROV_INCRSTATS(pd, error) { \ + (pd)->pd_sched_info.ks_ndispatches++; \ + if (error == CRYPTO_BUSY) \ + (pd)->pd_sched_info.ks_nbusy_rval++; \ + else if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED) \ + (pd)->pd_sched_info.ks_nfails++; \ +} + + +/* + * The following two macros should be + * #define KCF_OPS_CLASSSIZE (KCF_LAST_OPSCLASS - KCF_FIRST_OPSCLASS + 2) + * #define KCF_MAXMECHTAB KCF_MAXCIPHER + * + * However, doing that would involve reorganizing the header file a bit. + * When impl.h is broken up (bug# 4703218), this will be done. For now, + * we hardcode these values. + */ +#define KCF_OPS_CLASSSIZE 8 +#define KCF_MAXMECHTAB 32 + +/* + * Valid values for the state of a provider. The order of + * the elements is important. + * + * Routines which get a provider or the list of providers + * should pick only those that are either in KCF_PROV_READY state + * or in KCF_PROV_BUSY state. + */ +typedef enum { + KCF_PROV_ALLOCATED = 1, + KCF_PROV_UNVERIFIED, + KCF_PROV_VERIFICATION_FAILED, + /* + * state < KCF_PROV_READY means the provider can not + * be used at all. + */ + KCF_PROV_READY, + KCF_PROV_BUSY, + /* + * state > KCF_PROV_BUSY means the provider can not + * be used for new requests. + */ + KCF_PROV_FAILED, + /* + * Threads setting the following two states should do so only + * if the current state < KCF_PROV_DISABLED. + */ + KCF_PROV_DISABLED, + KCF_PROV_REMOVED, + KCF_PROV_FREED +} kcf_prov_state_t; + +#define KCF_IS_PROV_UNVERIFIED(pd) ((pd)->pd_state == KCF_PROV_UNVERIFIED) +#define KCF_IS_PROV_USABLE(pd) ((pd)->pd_state == KCF_PROV_READY || \ + (pd)->pd_state == KCF_PROV_BUSY) +#define KCF_IS_PROV_REMOVED(pd) ((pd)->pd_state >= KCF_PROV_REMOVED) + +/* Internal flags valid for pd_flags field */ +#define KCF_PROV_RESTRICTED 0x40000000 +#define KCF_LPROV_MEMBER 0x80000000 /* is member of a logical provider */ + +/* + * A provider descriptor structure. There is one such structure per + * provider. It is allocated and initialized at registration time and + * freed when the provider unregisters. + * + * pd_prov_type: Provider type, hardware or software + * pd_sid: Session ID of the provider used by kernel clients. + * This is valid only for session-oriented providers. + * pd_refcnt: Reference counter to this provider descriptor + * pd_irefcnt: References held by the framework internal structs + * pd_lock: lock protects pd_state and pd_provider_list + * pd_state: State value of the provider + * pd_provider_list: Used to cross-reference logical providers and their + * members. Not used for software providers. + * pd_resume_cv: cv to wait for state to change from KCF_PROV_BUSY + * pd_prov_handle: Provider handle specified by provider + * pd_ops_vector: The ops vector specified by Provider + * pd_mech_indx: Lookup table which maps a core framework mechanism + * number to an index in pd_mechanisms array + * pd_mechanisms: Array of mechanisms supported by the provider, specified + * by the provider during registration + * pd_sched_info: Scheduling information associated with the provider + * pd_mech_list_count: The number of entries in pi_mechanisms, specified + * by the provider during registration + * pd_name: Device name or module name + * pd_instance: Device instance + * pd_module_id: Module ID returned by modload + * pd_mctlp: Pointer to modctl structure for this provider + * pd_remove_cv: cv to wait on while the provider queue drains + * pd_description: Provider description string + * pd_flags bitwise OR of pi_flags from crypto_provider_info_t + * and other internal flags defined above. + * pd_hash_limit Maximum data size that hash mechanisms of this provider + * can support. + * pd_kcf_prov_handle: KCF-private handle assigned by KCF + * pd_prov_id: Identification # assigned by KCF to provider + * pd_kstat: kstat associated with the provider + * pd_ks_data: kstat data + */ +typedef struct kcf_provider_desc { + crypto_provider_type_t pd_prov_type; + crypto_session_id_t pd_sid; + uint_t pd_refcnt; + uint_t pd_irefcnt; + kmutex_t pd_lock; + kcf_prov_state_t pd_state; + struct kcf_provider_list *pd_provider_list; + kcondvar_t pd_resume_cv; + crypto_provider_handle_t pd_prov_handle; + crypto_ops_t *pd_ops_vector; + ushort_t pd_mech_indx[KCF_OPS_CLASSSIZE]\ + [KCF_MAXMECHTAB]; + crypto_mech_info_t *pd_mechanisms; + kcf_sched_info_t pd_sched_info; + uint_t pd_mech_list_count; + // char *pd_name; + // uint_t pd_instance; + // int pd_module_id; + // struct modctl *pd_mctlp; + kcondvar_t pd_remove_cv; + char *pd_description; + uint_t pd_flags; + uint_t pd_hash_limit; + crypto_kcf_provider_handle_t pd_kcf_prov_handle; + crypto_provider_id_t pd_prov_id; + kstat_t *pd_kstat; + kcf_prov_stats_t pd_ks_data; +} kcf_provider_desc_t; + +/* useful for making a list of providers */ +typedef struct kcf_provider_list { + struct kcf_provider_list *pl_next; + struct kcf_provider_desc *pl_provider; +} kcf_provider_list_t; + +/* atomic operations in linux implictly form a memory barrier */ +#define membar_exit() + +/* + * If a component has a reference to a kcf_provider_desc_t, + * it REFHOLD()s. A new provider descriptor which is referenced only + * by the providers table has a reference counter of one. + */ +#define KCF_PROV_REFHOLD(desc) { \ + atomic_add_32(&(desc)->pd_refcnt, 1); \ + ASSERT((desc)->pd_refcnt != 0); \ +} + +#define KCF_PROV_IREFHOLD(desc) { \ + atomic_add_32(&(desc)->pd_irefcnt, 1); \ + ASSERT((desc)->pd_irefcnt != 0); \ +} + +#define KCF_PROV_IREFRELE(desc) { \ + ASSERT((desc)->pd_irefcnt != 0); \ + membar_exit(); \ + if (atomic_add_32_nv(&(desc)->pd_irefcnt, -1) == 0) { \ + cv_broadcast(&(desc)->pd_remove_cv); \ + } \ +} + +#define KCF_PROV_REFHELD(desc) ((desc)->pd_refcnt >= 1) + +#define KCF_PROV_REFRELE(desc) { \ + ASSERT((desc)->pd_refcnt != 0); \ + membar_exit(); \ + if (atomic_add_32_nv(&(desc)->pd_refcnt, -1) == 0) { \ + kcf_provider_zero_refcnt((desc)); \ + } \ +} + + +/* list of crypto_mech_info_t valid as the second mech in a dual operation */ + +typedef struct crypto_mech_info_list { + struct crypto_mech_info_list *ml_next; + crypto_mech_type_t ml_kcf_mechid; /* KCF's id */ + crypto_mech_info_t ml_mech_info; +} crypto_mech_info_list_t; + +/* + * An element in a mechanism provider descriptors chain. + * The kcf_prov_mech_desc_t is duplicated in every chain the provider belongs + * to. This is a small tradeoff memory vs mutex spinning time to access the + * common provider field. + */ + +typedef struct kcf_prov_mech_desc { + struct kcf_mech_entry *pm_me; /* Back to the head */ + struct kcf_prov_mech_desc *pm_next; /* Next in the chain */ + crypto_mech_info_t pm_mech_info; /* Provider mech info */ + crypto_mech_info_list_t *pm_mi_list; /* list for duals */ + kcf_provider_desc_t *pm_prov_desc; /* Common desc. */ +} kcf_prov_mech_desc_t; + +/* and the notation shortcuts ... */ +#define pm_provider_type pm_prov_desc.pd_provider_type +#define pm_provider_handle pm_prov_desc.pd_provider_handle +#define pm_ops_vector pm_prov_desc.pd_ops_vector + + +#define KCF_CPU_PAD (128 - sizeof (crypto_mech_name_t) - \ + sizeof (crypto_mech_type_t) - \ + sizeof (kmutex_t) - 2 * sizeof (kcf_prov_mech_desc_t *) - \ + sizeof (int) - sizeof (uint32_t) - sizeof (size_t)) + +/* + * A mechanism entry in an xxx_mech_tab[]. KCF_CPU_PAD needs + * to be adjusted if this structure is changed. + */ +typedef struct kcf_mech_entry { + crypto_mech_name_t me_name; /* mechanism name */ + crypto_mech_type_t me_mechid; /* Internal id for mechanism */ + kmutex_t me_mutex; /* access protection */ + kcf_prov_mech_desc_t *me_hw_prov_chain; /* list of HW providers */ + kcf_prov_mech_desc_t *me_sw_prov; /* SW provider */ + /* + * Number of HW providers in the chain. There is only one + * SW provider. So, we need only a count of HW providers. + */ + int me_num_hwprov; + /* + * When a SW provider is present, this is the generation number that + * ensures no objects from old SW providers are used in the new one + */ + uint32_t me_gen_swprov; + /* + * threshold for using hardware providers for this mech + */ + size_t me_threshold; + uint8_t me_pad[KCF_CPU_PAD]; +} kcf_mech_entry_t; + +/* + * A policy descriptor structure. It is allocated and initialized + * when administrative ioctls load disabled mechanisms. + * + * pd_prov_type: Provider type, hardware or software + * pd_name: Device name or module name. + * pd_instance: Device instance. + * pd_refcnt: Reference counter for this policy descriptor + * pd_mutex: Protects array and count of disabled mechanisms. + * pd_disabled_count: Count of disabled mechanisms. + * pd_disabled_mechs: Array of disabled mechanisms. + */ +typedef struct kcf_policy_desc { + crypto_provider_type_t pd_prov_type; + char *pd_name; + uint_t pd_instance; + uint_t pd_refcnt; + kmutex_t pd_mutex; + uint_t pd_disabled_count; + crypto_mech_name_t *pd_disabled_mechs; +} kcf_policy_desc_t; + +/* + * If a component has a reference to a kcf_policy_desc_t, + * it REFHOLD()s. A new policy descriptor which is referenced only + * by the policy table has a reference count of one. + */ +#define KCF_POLICY_REFHOLD(desc) { \ + atomic_add_32(&(desc)->pd_refcnt, 1); \ + ASSERT((desc)->pd_refcnt != 0); \ +} + +/* + * Releases a reference to a policy descriptor. When the last + * reference is released, the descriptor is freed. + */ +#define KCF_POLICY_REFRELE(desc) { \ + ASSERT((desc)->pd_refcnt != 0); \ + membar_exit(); \ + if (atomic_add_32_nv(&(desc)->pd_refcnt, -1) == 0) \ + kcf_policy_free_desc(desc); \ +} + +/* + * This entry stores the name of a software module and its + * mechanisms. The mechanisms are 'hints' that are used to + * trigger loading of the module. + */ +typedef struct kcf_soft_conf_entry { + struct kcf_soft_conf_entry *ce_next; + char *ce_name; + crypto_mech_name_t *ce_mechs; + uint_t ce_count; +} kcf_soft_conf_entry_t; + +extern kmutex_t soft_config_mutex; +extern kcf_soft_conf_entry_t *soft_config_list; + +/* + * Global tables. The sizes are from the predefined PKCS#11 v2.20 mechanisms, + * with a margin of few extra empty entry points + */ + +#define KCF_MAXDIGEST 16 /* Digests */ +#define KCF_MAXCIPHER 64 /* Ciphers */ +#define KCF_MAXMAC 40 /* Message authentication codes */ +#define KCF_MAXSIGN 24 /* Sign/Verify */ +#define KCF_MAXKEYOPS 116 /* Key generation and derivation */ +#define KCF_MAXMISC 16 /* Others ... */ + +#define KCF_MAXMECHS KCF_MAXDIGEST + KCF_MAXCIPHER + KCF_MAXMAC + \ + KCF_MAXSIGN + KCF_MAXKEYOPS + \ + KCF_MAXMISC + +extern kcf_mech_entry_t kcf_digest_mechs_tab[]; +extern kcf_mech_entry_t kcf_cipher_mechs_tab[]; +extern kcf_mech_entry_t kcf_mac_mechs_tab[]; +extern kcf_mech_entry_t kcf_sign_mechs_tab[]; +extern kcf_mech_entry_t kcf_keyops_mechs_tab[]; +extern kcf_mech_entry_t kcf_misc_mechs_tab[]; + +extern kmutex_t kcf_mech_tabs_lock; + +typedef enum { + KCF_DIGEST_CLASS = 1, + KCF_CIPHER_CLASS, + KCF_MAC_CLASS, + KCF_SIGN_CLASS, + KCF_KEYOPS_CLASS, + KCF_MISC_CLASS +} kcf_ops_class_t; + +#define KCF_FIRST_OPSCLASS KCF_DIGEST_CLASS +#define KCF_LAST_OPSCLASS KCF_MISC_CLASS + +/* The table of all the kcf_xxx_mech_tab[]s, indexed by kcf_ops_class */ + +typedef struct kcf_mech_entry_tab { + int met_size; /* Size of the met_tab[] */ + kcf_mech_entry_t *met_tab; /* the table */ +} kcf_mech_entry_tab_t; + +extern kcf_mech_entry_tab_t kcf_mech_tabs_tab[]; + +#define KCF_MECHID(class, index) \ + (((crypto_mech_type_t)(class) << 32) | (crypto_mech_type_t)(index)) + +#define KCF_MECH2CLASS(mech_type) ((kcf_ops_class_t)((mech_type) >> 32)) + +#define KCF_MECH2INDEX(mech_type) ((int)(mech_type)) + +#define KCF_TO_PROV_MECH_INDX(pd, mech_type) \ + ((pd)->pd_mech_indx[KCF_MECH2CLASS(mech_type)] \ + [KCF_MECH2INDEX(mech_type)]) + +#define KCF_TO_PROV_MECHINFO(pd, mech_type) \ + ((pd)->pd_mechanisms[KCF_TO_PROV_MECH_INDX(pd, mech_type)]) + +#define KCF_TO_PROV_MECHNUM(pd, mech_type) \ + (KCF_TO_PROV_MECHINFO(pd, mech_type).cm_mech_number) + +#define KCF_CAN_SHARE_OPSTATE(pd, mech_type) \ + ((KCF_TO_PROV_MECHINFO(pd, mech_type).cm_mech_flags) & \ + CRYPTO_CAN_SHARE_OPSTATE) + +/* ps_refcnt is protected by cm_lock in the crypto_minor structure */ +typedef struct crypto_provider_session { + struct crypto_provider_session *ps_next; + crypto_session_id_t ps_session; + kcf_provider_desc_t *ps_provider; + kcf_provider_desc_t *ps_real_provider; + uint_t ps_refcnt; +} crypto_provider_session_t; + +typedef struct crypto_session_data { + kmutex_t sd_lock; + kcondvar_t sd_cv; + uint32_t sd_flags; + int sd_pre_approved_amount; + crypto_ctx_t *sd_digest_ctx; + crypto_ctx_t *sd_encr_ctx; + crypto_ctx_t *sd_decr_ctx; + crypto_ctx_t *sd_sign_ctx; + crypto_ctx_t *sd_verify_ctx; + crypto_ctx_t *sd_sign_recover_ctx; + crypto_ctx_t *sd_verify_recover_ctx; + kcf_provider_desc_t *sd_provider; + void *sd_find_init_cookie; + crypto_provider_session_t *sd_provider_session; +} crypto_session_data_t; + +#define CRYPTO_SESSION_IN_USE 0x00000001 +#define CRYPTO_SESSION_IS_BUSY 0x00000002 +#define CRYPTO_SESSION_IS_CLOSED 0x00000004 + +#define KCF_MAX_PIN_LEN 1024 + +/* + * Per-minor info. + * + * cm_lock protects everything in this structure except for cm_refcnt. + */ +typedef struct crypto_minor { + uint_t cm_refcnt; + kmutex_t cm_lock; + kcondvar_t cm_cv; + crypto_session_data_t **cm_session_table; + uint_t cm_session_table_count; + kcf_provider_desc_t **cm_provider_array; + uint_t cm_provider_count; + crypto_provider_session_t *cm_provider_session; +} crypto_minor_t; + +/* + * Return codes for internal functions + */ +#define KCF_SUCCESS 0x0 /* Successful call */ +#define KCF_INVALID_MECH_NUMBER 0x1 /* invalid mechanism number */ +#define KCF_INVALID_MECH_NAME 0x2 /* invalid mechanism name */ +#define KCF_INVALID_MECH_CLASS 0x3 /* invalid mechanism class */ +#define KCF_MECH_TAB_FULL 0x4 /* Need more room in the mech tabs. */ +#define KCF_INVALID_INDX ((ushort_t)-1) + +/* + * kCF internal mechanism and function group for tracking RNG providers. + */ +#define SUN_RANDOM "random" +#define CRYPTO_FG_RANDOM 0x80000000 /* generate_random() */ + +/* + * Wrappers for ops vectors. In the wrapper definitions below, the pd + * argument always corresponds to a pointer to a provider descriptor + * of type kcf_prov_desc_t. + */ + +#define KCF_PROV_CONTROL_OPS(pd) ((pd)->pd_ops_vector->co_control_ops) +#define KCF_PROV_CTX_OPS(pd) ((pd)->pd_ops_vector->co_ctx_ops) +#define KCF_PROV_DIGEST_OPS(pd) ((pd)->pd_ops_vector->co_digest_ops) +#define KCF_PROV_CIPHER_OPS(pd) ((pd)->pd_ops_vector->co_cipher_ops) +#define KCF_PROV_MAC_OPS(pd) ((pd)->pd_ops_vector->co_mac_ops) +#define KCF_PROV_SIGN_OPS(pd) ((pd)->pd_ops_vector->co_sign_ops) +#define KCF_PROV_VERIFY_OPS(pd) ((pd)->pd_ops_vector->co_verify_ops) +#define KCF_PROV_DUAL_OPS(pd) ((pd)->pd_ops_vector->co_dual_ops) +#define KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) \ + ((pd)->pd_ops_vector->co_dual_cipher_mac_ops) +#define KCF_PROV_RANDOM_OPS(pd) ((pd)->pd_ops_vector->co_random_ops) +#define KCF_PROV_SESSION_OPS(pd) ((pd)->pd_ops_vector->co_session_ops) +#define KCF_PROV_OBJECT_OPS(pd) ((pd)->pd_ops_vector->co_object_ops) +#define KCF_PROV_KEY_OPS(pd) ((pd)->pd_ops_vector->co_key_ops) +#define KCF_PROV_PROVIDER_OPS(pd) ((pd)->pd_ops_vector->co_provider_ops) +#define KCF_PROV_MECH_OPS(pd) ((pd)->pd_ops_vector->co_mech_ops) +#define KCF_PROV_NOSTORE_KEY_OPS(pd) \ + ((pd)->pd_ops_vector->co_nostore_key_ops) + +/* + * Wrappers for crypto_control_ops(9S) entry points. + */ + +#define KCF_PROV_STATUS(pd, status) ( \ + (KCF_PROV_CONTROL_OPS(pd) && \ + KCF_PROV_CONTROL_OPS(pd)->provider_status) ? \ + KCF_PROV_CONTROL_OPS(pd)->provider_status( \ + (pd)->pd_prov_handle, status) : \ + CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_ctx_ops(9S) entry points. + */ + +#define KCF_PROV_CREATE_CTX_TEMPLATE(pd, mech, key, template, size, req) ( \ + (KCF_PROV_CTX_OPS(pd) && KCF_PROV_CTX_OPS(pd)->create_ctx_template) ? \ + KCF_PROV_CTX_OPS(pd)->create_ctx_template( \ + (pd)->pd_prov_handle, mech, key, template, size, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_FREE_CONTEXT(pd, ctx) ( \ + (KCF_PROV_CTX_OPS(pd) && KCF_PROV_CTX_OPS(pd)->free_context) ? \ + KCF_PROV_CTX_OPS(pd)->free_context(ctx) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_COPYIN_MECH(pd, umech, kmech, errorp, mode) ( \ + (KCF_PROV_MECH_OPS(pd) && KCF_PROV_MECH_OPS(pd)->copyin_mechanism) ? \ + KCF_PROV_MECH_OPS(pd)->copyin_mechanism( \ + (pd)->pd_prov_handle, umech, kmech, errorp, mode) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_COPYOUT_MECH(pd, kmech, umech, errorp, mode) ( \ + (KCF_PROV_MECH_OPS(pd) && KCF_PROV_MECH_OPS(pd)->copyout_mechanism) ? \ + KCF_PROV_MECH_OPS(pd)->copyout_mechanism( \ + (pd)->pd_prov_handle, kmech, umech, errorp, mode) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_FREE_MECH(pd, prov_mech) ( \ + (KCF_PROV_MECH_OPS(pd) && KCF_PROV_MECH_OPS(pd)->free_mechanism) ? \ + KCF_PROV_MECH_OPS(pd)->free_mechanism( \ + (pd)->pd_prov_handle, prov_mech) : CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_digest_ops(9S) entry points. + */ + +#define KCF_PROV_DIGEST_INIT(pd, ctx, mech, req) ( \ + (KCF_PROV_DIGEST_OPS(pd) && KCF_PROV_DIGEST_OPS(pd)->digest_init) ? \ + KCF_PROV_DIGEST_OPS(pd)->digest_init(ctx, mech, req) : \ + CRYPTO_NOT_SUPPORTED) + +/* + * The _ (underscore) in _digest is needed to avoid replacing the + * function digest(). + */ +#define KCF_PROV_DIGEST(pd, ctx, data, _digest, req) ( \ + (KCF_PROV_DIGEST_OPS(pd) && KCF_PROV_DIGEST_OPS(pd)->digest) ? \ + KCF_PROV_DIGEST_OPS(pd)->digest(ctx, data, _digest, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DIGEST_UPDATE(pd, ctx, data, req) ( \ + (KCF_PROV_DIGEST_OPS(pd) && KCF_PROV_DIGEST_OPS(pd)->digest_update) ? \ + KCF_PROV_DIGEST_OPS(pd)->digest_update(ctx, data, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DIGEST_KEY(pd, ctx, key, req) ( \ + (KCF_PROV_DIGEST_OPS(pd) && KCF_PROV_DIGEST_OPS(pd)->digest_key) ? \ + KCF_PROV_DIGEST_OPS(pd)->digest_key(ctx, key, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DIGEST_FINAL(pd, ctx, digest, req) ( \ + (KCF_PROV_DIGEST_OPS(pd) && KCF_PROV_DIGEST_OPS(pd)->digest_final) ? \ + KCF_PROV_DIGEST_OPS(pd)->digest_final(ctx, digest, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DIGEST_ATOMIC(pd, session, mech, data, digest, req) ( \ + (KCF_PROV_DIGEST_OPS(pd) && KCF_PROV_DIGEST_OPS(pd)->digest_atomic) ? \ + KCF_PROV_DIGEST_OPS(pd)->digest_atomic( \ + (pd)->pd_prov_handle, session, mech, data, digest, req) : \ + CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_cipher_ops(9S) entry points. + */ + +#define KCF_PROV_ENCRYPT_INIT(pd, ctx, mech, key, template, req) ( \ + (KCF_PROV_CIPHER_OPS(pd) && KCF_PROV_CIPHER_OPS(pd)->encrypt_init) ? \ + KCF_PROV_CIPHER_OPS(pd)->encrypt_init(ctx, mech, key, template, \ + req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_ENCRYPT(pd, ctx, plaintext, ciphertext, req) ( \ + (KCF_PROV_CIPHER_OPS(pd) && KCF_PROV_CIPHER_OPS(pd)->encrypt) ? \ + KCF_PROV_CIPHER_OPS(pd)->encrypt(ctx, plaintext, ciphertext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_ENCRYPT_UPDATE(pd, ctx, plaintext, ciphertext, req) ( \ + (KCF_PROV_CIPHER_OPS(pd) && KCF_PROV_CIPHER_OPS(pd)->encrypt_update) ? \ + KCF_PROV_CIPHER_OPS(pd)->encrypt_update(ctx, plaintext, \ + ciphertext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_ENCRYPT_FINAL(pd, ctx, ciphertext, req) ( \ + (KCF_PROV_CIPHER_OPS(pd) && KCF_PROV_CIPHER_OPS(pd)->encrypt_final) ? \ + KCF_PROV_CIPHER_OPS(pd)->encrypt_final(ctx, ciphertext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_ENCRYPT_ATOMIC(pd, session, mech, key, plaintext, ciphertext, \ + template, req) ( \ + (KCF_PROV_CIPHER_OPS(pd) && KCF_PROV_CIPHER_OPS(pd)->encrypt_atomic) ? \ + KCF_PROV_CIPHER_OPS(pd)->encrypt_atomic( \ + (pd)->pd_prov_handle, session, mech, key, plaintext, ciphertext, \ + template, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DECRYPT_INIT(pd, ctx, mech, key, template, req) ( \ + (KCF_PROV_CIPHER_OPS(pd) && KCF_PROV_CIPHER_OPS(pd)->decrypt_init) ? \ + KCF_PROV_CIPHER_OPS(pd)->decrypt_init(ctx, mech, key, template, \ + req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DECRYPT(pd, ctx, ciphertext, plaintext, req) ( \ + (KCF_PROV_CIPHER_OPS(pd) && KCF_PROV_CIPHER_OPS(pd)->decrypt) ? \ + KCF_PROV_CIPHER_OPS(pd)->decrypt(ctx, ciphertext, plaintext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DECRYPT_UPDATE(pd, ctx, ciphertext, plaintext, req) ( \ + (KCF_PROV_CIPHER_OPS(pd) && KCF_PROV_CIPHER_OPS(pd)->decrypt_update) ? \ + KCF_PROV_CIPHER_OPS(pd)->decrypt_update(ctx, ciphertext, \ + plaintext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DECRYPT_FINAL(pd, ctx, plaintext, req) ( \ + (KCF_PROV_CIPHER_OPS(pd) && KCF_PROV_CIPHER_OPS(pd)->decrypt_final) ? \ + KCF_PROV_CIPHER_OPS(pd)->decrypt_final(ctx, plaintext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DECRYPT_ATOMIC(pd, session, mech, key, ciphertext, plaintext, \ + template, req) ( \ + (KCF_PROV_CIPHER_OPS(pd) && KCF_PROV_CIPHER_OPS(pd)->decrypt_atomic) ? \ + KCF_PROV_CIPHER_OPS(pd)->decrypt_atomic( \ + (pd)->pd_prov_handle, session, mech, key, ciphertext, plaintext, \ + template, req) : \ + CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_mac_ops(9S) entry points. + */ + +#define KCF_PROV_MAC_INIT(pd, ctx, mech, key, template, req) ( \ + (KCF_PROV_MAC_OPS(pd) && KCF_PROV_MAC_OPS(pd)->mac_init) ? \ + KCF_PROV_MAC_OPS(pd)->mac_init(ctx, mech, key, template, req) \ + : CRYPTO_NOT_SUPPORTED) + +/* + * The _ (underscore) in _mac is needed to avoid replacing the + * function mac(). + */ +#define KCF_PROV_MAC(pd, ctx, data, _mac, req) ( \ + (KCF_PROV_MAC_OPS(pd) && KCF_PROV_MAC_OPS(pd)->mac) ? \ + KCF_PROV_MAC_OPS(pd)->mac(ctx, data, _mac, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_MAC_UPDATE(pd, ctx, data, req) ( \ + (KCF_PROV_MAC_OPS(pd) && KCF_PROV_MAC_OPS(pd)->mac_update) ? \ + KCF_PROV_MAC_OPS(pd)->mac_update(ctx, data, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_MAC_FINAL(pd, ctx, mac, req) ( \ + (KCF_PROV_MAC_OPS(pd) && KCF_PROV_MAC_OPS(pd)->mac_final) ? \ + KCF_PROV_MAC_OPS(pd)->mac_final(ctx, mac, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_MAC_ATOMIC(pd, session, mech, key, data, mac, template, \ + req) ( \ + (KCF_PROV_MAC_OPS(pd) && KCF_PROV_MAC_OPS(pd)->mac_atomic) ? \ + KCF_PROV_MAC_OPS(pd)->mac_atomic( \ + (pd)->pd_prov_handle, session, mech, key, data, mac, template, \ + req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_MAC_VERIFY_ATOMIC(pd, session, mech, key, data, mac, \ + template, req) ( \ + (KCF_PROV_MAC_OPS(pd) && KCF_PROV_MAC_OPS(pd)->mac_verify_atomic) ? \ + KCF_PROV_MAC_OPS(pd)->mac_verify_atomic( \ + (pd)->pd_prov_handle, session, mech, key, data, mac, template, \ + req) : \ + CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_sign_ops(9S) entry points. + */ + +#define KCF_PROV_SIGN_INIT(pd, ctx, mech, key, template, req) ( \ + (KCF_PROV_SIGN_OPS(pd) && KCF_PROV_SIGN_OPS(pd)->sign_init) ? \ + KCF_PROV_SIGN_OPS(pd)->sign_init( \ + ctx, mech, key, template, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SIGN(pd, ctx, data, sig, req) ( \ + (KCF_PROV_SIGN_OPS(pd) && KCF_PROV_SIGN_OPS(pd)->sign) ? \ + KCF_PROV_SIGN_OPS(pd)->sign(ctx, data, sig, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SIGN_UPDATE(pd, ctx, data, req) ( \ + (KCF_PROV_SIGN_OPS(pd) && KCF_PROV_SIGN_OPS(pd)->sign_update) ? \ + KCF_PROV_SIGN_OPS(pd)->sign_update(ctx, data, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SIGN_FINAL(pd, ctx, sig, req) ( \ + (KCF_PROV_SIGN_OPS(pd) && KCF_PROV_SIGN_OPS(pd)->sign_final) ? \ + KCF_PROV_SIGN_OPS(pd)->sign_final(ctx, sig, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SIGN_ATOMIC(pd, session, mech, key, data, template, \ + sig, req) ( \ + (KCF_PROV_SIGN_OPS(pd) && KCF_PROV_SIGN_OPS(pd)->sign_atomic) ? \ + KCF_PROV_SIGN_OPS(pd)->sign_atomic( \ + (pd)->pd_prov_handle, session, mech, key, data, sig, template, \ + req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SIGN_RECOVER_INIT(pd, ctx, mech, key, template, \ + req) ( \ + (KCF_PROV_SIGN_OPS(pd) && KCF_PROV_SIGN_OPS(pd)->sign_recover_init) ? \ + KCF_PROV_SIGN_OPS(pd)->sign_recover_init(ctx, mech, key, template, \ + req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SIGN_RECOVER(pd, ctx, data, sig, req) ( \ + (KCF_PROV_SIGN_OPS(pd) && KCF_PROV_SIGN_OPS(pd)->sign_recover) ? \ + KCF_PROV_SIGN_OPS(pd)->sign_recover(ctx, data, sig, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SIGN_RECOVER_ATOMIC(pd, session, mech, key, data, template, \ + sig, req) ( \ + (KCF_PROV_SIGN_OPS(pd) && \ + KCF_PROV_SIGN_OPS(pd)->sign_recover_atomic) ? \ + KCF_PROV_SIGN_OPS(pd)->sign_recover_atomic( \ + (pd)->pd_prov_handle, session, mech, key, data, sig, template, \ + req) : CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_verify_ops(9S) entry points. + */ + +#define KCF_PROV_VERIFY_INIT(pd, ctx, mech, key, template, req) ( \ + (KCF_PROV_VERIFY_OPS(pd) && KCF_PROV_VERIFY_OPS(pd)->verify_init) ? \ + KCF_PROV_VERIFY_OPS(pd)->verify_init(ctx, mech, key, template, \ + req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_VERIFY(pd, ctx, data, sig, req) ( \ + (KCF_PROV_VERIFY_OPS(pd) && KCF_PROV_VERIFY_OPS(pd)->do_verify) ? \ + KCF_PROV_VERIFY_OPS(pd)->do_verify(ctx, data, sig, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_VERIFY_UPDATE(pd, ctx, data, req) ( \ + (KCF_PROV_VERIFY_OPS(pd) && KCF_PROV_VERIFY_OPS(pd)->verify_update) ? \ + KCF_PROV_VERIFY_OPS(pd)->verify_update(ctx, data, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_VERIFY_FINAL(pd, ctx, sig, req) ( \ + (KCF_PROV_VERIFY_OPS(pd) && KCF_PROV_VERIFY_OPS(pd)->verify_final) ? \ + KCF_PROV_VERIFY_OPS(pd)->verify_final(ctx, sig, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_VERIFY_ATOMIC(pd, session, mech, key, data, template, sig, \ + req) ( \ + (KCF_PROV_VERIFY_OPS(pd) && KCF_PROV_VERIFY_OPS(pd)->verify_atomic) ? \ + KCF_PROV_VERIFY_OPS(pd)->verify_atomic( \ + (pd)->pd_prov_handle, session, mech, key, data, sig, template, \ + req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_VERIFY_RECOVER_INIT(pd, ctx, mech, key, template, \ + req) ( \ + (KCF_PROV_VERIFY_OPS(pd) && \ + KCF_PROV_VERIFY_OPS(pd)->verify_recover_init) ? \ + KCF_PROV_VERIFY_OPS(pd)->verify_recover_init(ctx, mech, key, \ + template, req) : CRYPTO_NOT_SUPPORTED) + +/* verify_recover() CSPI routine has different argument order than verify() */ +#define KCF_PROV_VERIFY_RECOVER(pd, ctx, sig, data, req) ( \ + (KCF_PROV_VERIFY_OPS(pd) && KCF_PROV_VERIFY_OPS(pd)->verify_recover) ? \ + KCF_PROV_VERIFY_OPS(pd)->verify_recover(ctx, sig, data, req) : \ + CRYPTO_NOT_SUPPORTED) + +/* + * verify_recover_atomic() CSPI routine has different argument order + * than verify_atomic(). + */ +#define KCF_PROV_VERIFY_RECOVER_ATOMIC(pd, session, mech, key, sig, \ + template, data, req) ( \ + (KCF_PROV_VERIFY_OPS(pd) && \ + KCF_PROV_VERIFY_OPS(pd)->verify_recover_atomic) ? \ + KCF_PROV_VERIFY_OPS(pd)->verify_recover_atomic( \ + (pd)->pd_prov_handle, session, mech, key, sig, data, template, \ + req) : CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_dual_ops(9S) entry points. + */ + +#define KCF_PROV_DIGEST_ENCRYPT_UPDATE(digest_ctx, encrypt_ctx, plaintext, \ + ciphertext, req) ( \ + (KCF_PROV_DUAL_OPS(pd) && \ + KCF_PROV_DUAL_OPS(pd)->digest_encrypt_update) ? \ + KCF_PROV_DUAL_OPS(pd)->digest_encrypt_update( \ + digest_ctx, encrypt_ctx, plaintext, ciphertext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DECRYPT_DIGEST_UPDATE(decrypt_ctx, digest_ctx, ciphertext, \ + plaintext, req) ( \ + (KCF_PROV_DUAL_OPS(pd) && \ + KCF_PROV_DUAL_OPS(pd)->decrypt_digest_update) ? \ + KCF_PROV_DUAL_OPS(pd)->decrypt_digest_update( \ + decrypt_ctx, digest_ctx, ciphertext, plaintext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SIGN_ENCRYPT_UPDATE(sign_ctx, encrypt_ctx, plaintext, \ + ciphertext, req) ( \ + (KCF_PROV_DUAL_OPS(pd) && \ + KCF_PROV_DUAL_OPS(pd)->sign_encrypt_update) ? \ + KCF_PROV_DUAL_OPS(pd)->sign_encrypt_update( \ + sign_ctx, encrypt_ctx, plaintext, ciphertext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_DECRYPT_VERIFY_UPDATE(decrypt_ctx, verify_ctx, ciphertext, \ + plaintext, req) ( \ + (KCF_PROV_DUAL_OPS(pd) && \ + KCF_PROV_DUAL_OPS(pd)->decrypt_verify_update) ? \ + KCF_PROV_DUAL_OPS(pd)->decrypt_verify_update( \ + decrypt_ctx, verify_ctx, ciphertext, plaintext, req) : \ + CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_dual_cipher_mac_ops(9S) entry points. + */ + +#define KCF_PROV_ENCRYPT_MAC_INIT(pd, ctx, encr_mech, encr_key, mac_mech, \ + mac_key, encr_ctx_template, mac_ctx_template, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->encrypt_mac_init) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->encrypt_mac_init( \ + ctx, encr_mech, encr_key, mac_mech, mac_key, encr_ctx_template, \ + mac_ctx_template, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_ENCRYPT_MAC(pd, ctx, plaintext, ciphertext, mac, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->encrypt_mac) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->encrypt_mac( \ + ctx, plaintext, ciphertext, mac, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_ENCRYPT_MAC_UPDATE(pd, ctx, plaintext, ciphertext, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->encrypt_mac_update) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->encrypt_mac_update( \ + ctx, plaintext, ciphertext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_ENCRYPT_MAC_FINAL(pd, ctx, ciphertext, mac, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->encrypt_mac_final) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->encrypt_mac_final( \ + ctx, ciphertext, mac, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_ENCRYPT_MAC_ATOMIC(pd, session, encr_mech, encr_key, \ + mac_mech, mac_key, plaintext, ciphertext, mac, \ + encr_ctx_template, mac_ctx_template, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->encrypt_mac_atomic) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->encrypt_mac_atomic( \ + (pd)->pd_prov_handle, session, encr_mech, encr_key, \ + mac_mech, mac_key, plaintext, ciphertext, mac, \ + encr_ctx_template, mac_ctx_template, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_MAC_DECRYPT_INIT(pd, ctx, mac_mech, mac_key, decr_mech, \ + decr_key, mac_ctx_template, decr_ctx_template, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_decrypt_init) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_decrypt_init( \ + ctx, mac_mech, mac_key, decr_mech, decr_key, mac_ctx_template, \ + decr_ctx_template, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_MAC_DECRYPT(pd, ctx, ciphertext, mac, plaintext, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_decrypt) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_decrypt( \ + ctx, ciphertext, mac, plaintext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_MAC_DECRYPT_UPDATE(pd, ctx, ciphertext, plaintext, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_decrypt_update) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_decrypt_update( \ + ctx, ciphertext, plaintext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_MAC_DECRYPT_FINAL(pd, ctx, mac, plaintext, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_decrypt_final) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_decrypt_final( \ + ctx, mac, plaintext, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_MAC_DECRYPT_ATOMIC(pd, session, mac_mech, mac_key, \ + decr_mech, decr_key, ciphertext, mac, plaintext, \ + mac_ctx_template, decr_ctx_template, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_decrypt_atomic) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_decrypt_atomic( \ + (pd)->pd_prov_handle, session, mac_mech, mac_key, \ + decr_mech, decr_key, ciphertext, mac, plaintext, \ + mac_ctx_template, decr_ctx_template, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_MAC_VERIFY_DECRYPT_ATOMIC(pd, session, mac_mech, mac_key, \ + decr_mech, decr_key, ciphertext, mac, plaintext, \ + mac_ctx_template, decr_ctx_template, req) ( \ + (KCF_PROV_DUAL_CIPHER_MAC_OPS(pd) && \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_verify_decrypt_atomic \ + != NULL) ? \ + KCF_PROV_DUAL_CIPHER_MAC_OPS(pd)->mac_verify_decrypt_atomic( \ + (pd)->pd_prov_handle, session, mac_mech, mac_key, \ + decr_mech, decr_key, ciphertext, mac, plaintext, \ + mac_ctx_template, decr_ctx_template, req) : \ + CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_random_number_ops(9S) entry points. + */ + +#define KCF_PROV_SEED_RANDOM(pd, session, buf, len, est, flags, req) ( \ + (KCF_PROV_RANDOM_OPS(pd) && KCF_PROV_RANDOM_OPS(pd)->seed_random) ? \ + KCF_PROV_RANDOM_OPS(pd)->seed_random((pd)->pd_prov_handle, \ + session, buf, len, est, flags, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_GENERATE_RANDOM(pd, session, buf, len, req) ( \ + (KCF_PROV_RANDOM_OPS(pd) && \ + KCF_PROV_RANDOM_OPS(pd)->generate_random) ? \ + KCF_PROV_RANDOM_OPS(pd)->generate_random((pd)->pd_prov_handle, \ + session, buf, len, req) : CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_session_ops(9S) entry points. + * + * ops_pd is the provider descriptor that supplies the ops_vector. + * pd is the descriptor that supplies the provider handle. + * Only session open/close needs two handles. + */ + +#define KCF_PROV_SESSION_OPEN(ops_pd, session, req, pd) ( \ + (KCF_PROV_SESSION_OPS(ops_pd) && \ + KCF_PROV_SESSION_OPS(ops_pd)->session_open) ? \ + KCF_PROV_SESSION_OPS(ops_pd)->session_open((pd)->pd_prov_handle, \ + session, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SESSION_CLOSE(ops_pd, session, req, pd) ( \ + (KCF_PROV_SESSION_OPS(ops_pd) && \ + KCF_PROV_SESSION_OPS(ops_pd)->session_close) ? \ + KCF_PROV_SESSION_OPS(ops_pd)->session_close((pd)->pd_prov_handle, \ + session, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SESSION_LOGIN(pd, session, user_type, pin, len, req) ( \ + (KCF_PROV_SESSION_OPS(pd) && \ + KCF_PROV_SESSION_OPS(pd)->session_login) ? \ + KCF_PROV_SESSION_OPS(pd)->session_login((pd)->pd_prov_handle, \ + session, user_type, pin, len, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SESSION_LOGOUT(pd, session, req) ( \ + (KCF_PROV_SESSION_OPS(pd) && \ + KCF_PROV_SESSION_OPS(pd)->session_logout) ? \ + KCF_PROV_SESSION_OPS(pd)->session_logout((pd)->pd_prov_handle, \ + session, req) : CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_object_ops(9S) entry points. + */ + +#define KCF_PROV_OBJECT_CREATE(pd, session, template, count, object, req) ( \ + (KCF_PROV_OBJECT_OPS(pd) && KCF_PROV_OBJECT_OPS(pd)->object_create) ? \ + KCF_PROV_OBJECT_OPS(pd)->object_create((pd)->pd_prov_handle, \ + session, template, count, object, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_OBJECT_COPY(pd, session, object, template, count, \ + new_object, req) ( \ + (KCF_PROV_OBJECT_OPS(pd) && KCF_PROV_OBJECT_OPS(pd)->object_copy) ? \ + KCF_PROV_OBJECT_OPS(pd)->object_copy((pd)->pd_prov_handle, \ + session, object, template, count, new_object, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_OBJECT_DESTROY(pd, session, object, req) ( \ + (KCF_PROV_OBJECT_OPS(pd) && KCF_PROV_OBJECT_OPS(pd)->object_destroy) ? \ + KCF_PROV_OBJECT_OPS(pd)->object_destroy((pd)->pd_prov_handle, \ + session, object, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_OBJECT_GET_SIZE(pd, session, object, size, req) ( \ + (KCF_PROV_OBJECT_OPS(pd) && \ + KCF_PROV_OBJECT_OPS(pd)->object_get_size) ? \ + KCF_PROV_OBJECT_OPS(pd)->object_get_size((pd)->pd_prov_handle, \ + session, object, size, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_OBJECT_GET_ATTRIBUTE_VALUE(pd, session, object, template, \ + count, req) ( \ + (KCF_PROV_OBJECT_OPS(pd) && \ + KCF_PROV_OBJECT_OPS(pd)->object_get_attribute_value) ? \ + KCF_PROV_OBJECT_OPS(pd)->object_get_attribute_value( \ + (pd)->pd_prov_handle, session, object, template, count, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_OBJECT_SET_ATTRIBUTE_VALUE(pd, session, object, template, \ + count, req) ( \ + (KCF_PROV_OBJECT_OPS(pd) && \ + KCF_PROV_OBJECT_OPS(pd)->object_set_attribute_value) ? \ + KCF_PROV_OBJECT_OPS(pd)->object_set_attribute_value( \ + (pd)->pd_prov_handle, session, object, template, count, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_OBJECT_FIND_INIT(pd, session, template, count, ppriv, \ + req) ( \ + (KCF_PROV_OBJECT_OPS(pd) && \ + KCF_PROV_OBJECT_OPS(pd)->object_find_init) ? \ + KCF_PROV_OBJECT_OPS(pd)->object_find_init((pd)->pd_prov_handle, \ + session, template, count, ppriv, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_OBJECT_FIND(pd, ppriv, objects, max_objects, object_count, \ + req) ( \ + (KCF_PROV_OBJECT_OPS(pd) && KCF_PROV_OBJECT_OPS(pd)->object_find) ? \ + KCF_PROV_OBJECT_OPS(pd)->object_find( \ + (pd)->pd_prov_handle, ppriv, objects, max_objects, object_count, \ + req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_OBJECT_FIND_FINAL(pd, ppriv, req) ( \ + (KCF_PROV_OBJECT_OPS(pd) && \ + KCF_PROV_OBJECT_OPS(pd)->object_find_final) ? \ + KCF_PROV_OBJECT_OPS(pd)->object_find_final( \ + (pd)->pd_prov_handle, ppriv, req) : CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_key_ops(9S) entry points. + */ + +#define KCF_PROV_KEY_GENERATE(pd, session, mech, template, count, object, \ + req) ( \ + (KCF_PROV_KEY_OPS(pd) && KCF_PROV_KEY_OPS(pd)->key_generate) ? \ + KCF_PROV_KEY_OPS(pd)->key_generate((pd)->pd_prov_handle, \ + session, mech, template, count, object, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_KEY_GENERATE_PAIR(pd, session, mech, pub_template, \ + pub_count, priv_template, priv_count, pub_key, priv_key, req) ( \ + (KCF_PROV_KEY_OPS(pd) && KCF_PROV_KEY_OPS(pd)->key_generate_pair) ? \ + KCF_PROV_KEY_OPS(pd)->key_generate_pair((pd)->pd_prov_handle, \ + session, mech, pub_template, pub_count, priv_template, \ + priv_count, pub_key, priv_key, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_KEY_WRAP(pd, session, mech, wrapping_key, key, wrapped_key, \ + wrapped_key_len, req) ( \ + (KCF_PROV_KEY_OPS(pd) && KCF_PROV_KEY_OPS(pd)->key_wrap) ? \ + KCF_PROV_KEY_OPS(pd)->key_wrap((pd)->pd_prov_handle, \ + session, mech, wrapping_key, key, wrapped_key, wrapped_key_len, \ + req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_KEY_UNWRAP(pd, session, mech, unwrapping_key, wrapped_key, \ + wrapped_key_len, template, count, key, req) ( \ + (KCF_PROV_KEY_OPS(pd) && KCF_PROV_KEY_OPS(pd)->key_unwrap) ? \ + KCF_PROV_KEY_OPS(pd)->key_unwrap((pd)->pd_prov_handle, \ + session, mech, unwrapping_key, wrapped_key, wrapped_key_len, \ + template, count, key, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_KEY_DERIVE(pd, session, mech, base_key, template, count, \ + key, req) ( \ + (KCF_PROV_KEY_OPS(pd) && KCF_PROV_KEY_OPS(pd)->key_derive) ? \ + KCF_PROV_KEY_OPS(pd)->key_derive((pd)->pd_prov_handle, \ + session, mech, base_key, template, count, key, req) : \ + CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_KEY_CHECK(pd, mech, key) ( \ + (KCF_PROV_KEY_OPS(pd) && KCF_PROV_KEY_OPS(pd)->key_check) ? \ + KCF_PROV_KEY_OPS(pd)->key_check((pd)->pd_prov_handle, mech, key) : \ + CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_provider_management_ops(9S) entry points. + * + * ops_pd is the provider descriptor that supplies the ops_vector. + * pd is the descriptor that supplies the provider handle. + * Only ext_info needs two handles. + */ + +#define KCF_PROV_EXT_INFO(ops_pd, provext_info, req, pd) ( \ + (KCF_PROV_PROVIDER_OPS(ops_pd) && \ + KCF_PROV_PROVIDER_OPS(ops_pd)->ext_info) ? \ + KCF_PROV_PROVIDER_OPS(ops_pd)->ext_info((pd)->pd_prov_handle, \ + provext_info, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_INIT_TOKEN(pd, pin, pin_len, label, req) ( \ + (KCF_PROV_PROVIDER_OPS(pd) && KCF_PROV_PROVIDER_OPS(pd)->init_token) ? \ + KCF_PROV_PROVIDER_OPS(pd)->init_token((pd)->pd_prov_handle, \ + pin, pin_len, label, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_INIT_PIN(pd, session, pin, pin_len, req) ( \ + (KCF_PROV_PROVIDER_OPS(pd) && KCF_PROV_PROVIDER_OPS(pd)->init_pin) ? \ + KCF_PROV_PROVIDER_OPS(pd)->init_pin((pd)->pd_prov_handle, \ + session, pin, pin_len, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_SET_PIN(pd, session, old_pin, old_len, new_pin, new_len, \ + req) ( \ + (KCF_PROV_PROVIDER_OPS(pd) && KCF_PROV_PROVIDER_OPS(pd)->set_pin) ? \ + KCF_PROV_PROVIDER_OPS(pd)->set_pin((pd)->pd_prov_handle, \ + session, old_pin, old_len, new_pin, new_len, req) : \ + CRYPTO_NOT_SUPPORTED) + +/* + * Wrappers for crypto_nostore_key_ops(9S) entry points. + */ + +#define KCF_PROV_NOSTORE_KEY_GENERATE(pd, session, mech, template, count, \ + out_template, out_count, req) ( \ + (KCF_PROV_NOSTORE_KEY_OPS(pd) && \ + KCF_PROV_NOSTORE_KEY_OPS(pd)->nostore_key_generate) ? \ + KCF_PROV_NOSTORE_KEY_OPS(pd)->nostore_key_generate( \ + (pd)->pd_prov_handle, session, mech, template, count, \ + out_template, out_count, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_NOSTORE_KEY_GENERATE_PAIR(pd, session, mech, pub_template, \ + pub_count, priv_template, priv_count, out_pub_template, \ + out_pub_count, out_priv_template, out_priv_count, req) ( \ + (KCF_PROV_NOSTORE_KEY_OPS(pd) && \ + KCF_PROV_NOSTORE_KEY_OPS(pd)->nostore_key_generate_pair) ? \ + KCF_PROV_NOSTORE_KEY_OPS(pd)->nostore_key_generate_pair( \ + (pd)->pd_prov_handle, session, mech, pub_template, pub_count, \ + priv_template, priv_count, out_pub_template, out_pub_count, \ + out_priv_template, out_priv_count, req) : CRYPTO_NOT_SUPPORTED) + +#define KCF_PROV_NOSTORE_KEY_DERIVE(pd, session, mech, base_key, template, \ + count, out_template, out_count, req) ( \ + (KCF_PROV_NOSTORE_KEY_OPS(pd) && \ + KCF_PROV_NOSTORE_KEY_OPS(pd)->nostore_key_derive) ? \ + KCF_PROV_NOSTORE_KEY_OPS(pd)->nostore_key_derive( \ + (pd)->pd_prov_handle, session, mech, base_key, template, count, \ + out_template, out_count, req) : CRYPTO_NOT_SUPPORTED) + +/* + * The following routines are exported by the kcf module (/kernel/misc/kcf) + * to the crypto and cryptoadmin modules. + */ + +/* Digest/mac/cipher entry points that take a provider descriptor and session */ +extern int crypto_digest_single(crypto_context_t, crypto_data_t *, + crypto_data_t *, crypto_call_req_t *); + +extern int crypto_mac_single(crypto_context_t, crypto_data_t *, + crypto_data_t *, crypto_call_req_t *); + +extern int crypto_encrypt_single(crypto_context_t, crypto_data_t *, + crypto_data_t *, crypto_call_req_t *); + +extern int crypto_decrypt_single(crypto_context_t, crypto_data_t *, + crypto_data_t *, crypto_call_req_t *); + + +/* Other private digest/mac/cipher entry points not exported through k-API */ +extern int crypto_digest_key_prov(crypto_context_t, crypto_key_t *, + crypto_call_req_t *); + +/* Private sign entry points exported by KCF */ +extern int crypto_sign_single(crypto_context_t, crypto_data_t *, + crypto_data_t *, crypto_call_req_t *); + +extern int crypto_sign_recover_single(crypto_context_t, crypto_data_t *, + crypto_data_t *, crypto_call_req_t *); + +/* Private verify entry points exported by KCF */ +extern int crypto_verify_single(crypto_context_t, crypto_data_t *, + crypto_data_t *, crypto_call_req_t *); + +extern int crypto_verify_recover_single(crypto_context_t, crypto_data_t *, + crypto_data_t *, crypto_call_req_t *); + +/* Private dual operations entry points exported by KCF */ +extern int crypto_digest_encrypt_update(crypto_context_t, crypto_context_t, + crypto_data_t *, crypto_data_t *, crypto_call_req_t *); +extern int crypto_decrypt_digest_update(crypto_context_t, crypto_context_t, + crypto_data_t *, crypto_data_t *, crypto_call_req_t *); +extern int crypto_sign_encrypt_update(crypto_context_t, crypto_context_t, + crypto_data_t *, crypto_data_t *, crypto_call_req_t *); +extern int crypto_decrypt_verify_update(crypto_context_t, crypto_context_t, + crypto_data_t *, crypto_data_t *, crypto_call_req_t *); + +/* Random Number Generation */ +int crypto_seed_random(crypto_provider_handle_t provider, uchar_t *buf, + size_t len, crypto_call_req_t *req); +int crypto_generate_random(crypto_provider_handle_t provider, uchar_t *buf, + size_t len, crypto_call_req_t *req); + +/* Provider Management */ +int crypto_get_provider_info(crypto_provider_id_t id, + crypto_provider_info_t **info, crypto_call_req_t *req); +int crypto_get_provider_mechanisms(crypto_minor_t *, crypto_provider_id_t id, + uint_t *count, crypto_mech_name_t **list); +int crypto_init_token(crypto_provider_handle_t provider, char *pin, + size_t pin_len, char *label, crypto_call_req_t *); +int crypto_init_pin(crypto_provider_handle_t provider, char *pin, + size_t pin_len, crypto_call_req_t *req); +int crypto_set_pin(crypto_provider_handle_t provider, char *old_pin, + size_t old_len, char *new_pin, size_t new_len, crypto_call_req_t *req); +void crypto_free_provider_list(crypto_provider_entry_t *list, uint_t count); +void crypto_free_provider_info(crypto_provider_info_t *info); + +/* Administrative */ +int crypto_get_dev_list(uint_t *count, crypto_dev_list_entry_t **list); +int crypto_get_soft_list(uint_t *count, char **list, size_t *len); +int crypto_get_dev_info(char *name, uint_t instance, uint_t *count, + crypto_mech_name_t **list); +int crypto_get_soft_info(caddr_t name, uint_t *count, + crypto_mech_name_t **list); +int crypto_load_dev_disabled(char *name, uint_t instance, uint_t count, + crypto_mech_name_t *list); +int crypto_load_soft_disabled(caddr_t name, uint_t count, + crypto_mech_name_t *list); +int crypto_unload_soft_module(caddr_t path); +int crypto_load_soft_config(caddr_t name, uint_t count, + crypto_mech_name_t *list); +int crypto_load_door(uint_t did); +void crypto_free_mech_list(crypto_mech_name_t *list, uint_t count); +void crypto_free_dev_list(crypto_dev_list_entry_t *list, uint_t count); + +/* Miscellaneous */ +int crypto_get_mechanism_number(caddr_t name, crypto_mech_type_t *number); +int crypto_get_function_list(crypto_provider_id_t id, + crypto_function_list_t **list, int kmflag); +void crypto_free_function_list(crypto_function_list_t *list); +int crypto_build_permitted_mech_names(kcf_provider_desc_t *, + crypto_mech_name_t **, uint_t *, int); +extern void kcf_destroy_mech_tabs(void); +extern void kcf_init_mech_tabs(void); +extern int kcf_add_mech_provider(short, kcf_provider_desc_t *, + kcf_prov_mech_desc_t **); +extern void kcf_remove_mech_provider(char *, kcf_provider_desc_t *); +extern int kcf_get_mech_entry(crypto_mech_type_t, kcf_mech_entry_t **); +extern kcf_provider_desc_t *kcf_alloc_provider_desc(crypto_provider_info_t *); +extern void kcf_provider_zero_refcnt(kcf_provider_desc_t *); +extern void kcf_free_provider_desc(kcf_provider_desc_t *); +extern void kcf_soft_config_init(void); +extern int get_sw_provider_for_mech(crypto_mech_name_t, char **); +extern crypto_mech_type_t crypto_mech2id_common(char *, boolean_t); +extern void undo_register_provider(kcf_provider_desc_t *, boolean_t); +extern void redo_register_provider(kcf_provider_desc_t *); +extern void kcf_rnd_init(void); +extern boolean_t kcf_rngprov_check(void); +extern int kcf_rnd_get_pseudo_bytes(uint8_t *, size_t); +extern int kcf_rnd_get_bytes(uint8_t *, size_t, boolean_t, boolean_t); +extern int random_add_pseudo_entropy(uint8_t *, size_t, uint_t); +extern void kcf_rnd_schedule_timeout(boolean_t); +extern int crypto_uio_data(crypto_data_t *, uchar_t *, int, cmd_type_t, + void *, void (*update)(void)); +extern int crypto_mblk_data(crypto_data_t *, uchar_t *, int, cmd_type_t, + void *, void (*update)(void)); +extern int crypto_put_output_data(uchar_t *, crypto_data_t *, int); +extern int crypto_get_input_data(crypto_data_t *, uchar_t **, uchar_t *); +extern int crypto_copy_key_to_ctx(crypto_key_t *, crypto_key_t **, size_t *, + int kmflag); +extern int crypto_digest_data(crypto_data_t *, void *, uchar_t *, + void (*update)(void), void (*final)(void), uchar_t); +extern int crypto_update_iov(void *, crypto_data_t *, crypto_data_t *, + int (*cipher)(void *, caddr_t, size_t, crypto_data_t *), + void (*copy_block)(uint8_t *, uint64_t *)); +extern int crypto_update_uio(void *, crypto_data_t *, crypto_data_t *, + int (*cipher)(void *, caddr_t, size_t, crypto_data_t *), + void (*copy_block)(uint8_t *, uint64_t *)); +extern int crypto_update_mp(void *, crypto_data_t *, crypto_data_t *, + int (*cipher)(void *, caddr_t, size_t, crypto_data_t *), + void (*copy_block)(uint8_t *, uint64_t *)); +extern int crypto_get_key_attr(crypto_key_t *, crypto_attr_type_t, uchar_t **, + ssize_t *); + +/* Access to the provider's table */ +extern void kcf_prov_tab_destroy(void); +extern void kcf_prov_tab_init(void); +extern int kcf_prov_tab_add_provider(kcf_provider_desc_t *); +extern int kcf_prov_tab_rem_provider(crypto_provider_id_t); +extern kcf_provider_desc_t *kcf_prov_tab_lookup_by_name(char *); +extern kcf_provider_desc_t *kcf_prov_tab_lookup_by_dev(char *, uint_t); +extern int kcf_get_hw_prov_tab(uint_t *, kcf_provider_desc_t ***, int, + char *, uint_t, boolean_t); +extern int kcf_get_slot_list(uint_t *, kcf_provider_desc_t ***, boolean_t); +extern void kcf_free_provider_tab(uint_t, kcf_provider_desc_t **); +extern kcf_provider_desc_t *kcf_prov_tab_lookup(crypto_provider_id_t); +extern int kcf_get_sw_prov(crypto_mech_type_t, kcf_provider_desc_t **, + kcf_mech_entry_t **, boolean_t); + +/* Access to the policy table */ +extern boolean_t is_mech_disabled(kcf_provider_desc_t *, crypto_mech_name_t); +extern boolean_t is_mech_disabled_byname(crypto_provider_type_t, char *, + uint_t, crypto_mech_name_t); +extern void kcf_policy_tab_init(void); +extern void kcf_policy_free_desc(kcf_policy_desc_t *); +extern void kcf_policy_remove_by_name(char *, uint_t *, crypto_mech_name_t **); +extern void kcf_policy_remove_by_dev(char *, uint_t, uint_t *, + crypto_mech_name_t **); +extern kcf_policy_desc_t *kcf_policy_lookup_by_name(char *); +extern kcf_policy_desc_t *kcf_policy_lookup_by_dev(char *, uint_t); +extern int kcf_policy_load_soft_disabled(char *, uint_t, crypto_mech_name_t *, + uint_t *, crypto_mech_name_t **); +extern int kcf_policy_load_dev_disabled(char *, uint_t, uint_t, + crypto_mech_name_t *, uint_t *, crypto_mech_name_t **); +extern boolean_t in_soft_config_list(char *); + + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_CRYPTO_IMPL_H */ diff --git a/module/icp/include/sys/crypto/ioctl.h b/module/icp/include/sys/crypto/ioctl.h new file mode 100644 index 000000000..dd59ca7f2 --- /dev/null +++ b/module/icp/include/sys/crypto/ioctl.h @@ -0,0 +1,1483 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_CRYPTO_IOCTL_H +#define _SYS_CRYPTO_IOCTL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/zfs_context.h> +#include <sys/crypto/api.h> +#include <sys/crypto/spi.h> +#include <sys/crypto/common.h> + +#define CRYPTO_MAX_ATTRIBUTE_COUNT 128 + +#define CRYPTO_IOFLAGS_RW_SESSION 0x00000001 + +#define CRYPTO(x) (('y' << 8) | (x)) + +#define MAX_NUM_THRESHOLD 7 + +/* the PKCS11 Mechanisms */ +#define CKM_RC4 0x00000111 +#define CKM_DES3_ECB 0x00000132 +#define CKM_DES3_CBC 0x00000133 +#define CKM_MD5 0x00000210 +#define CKM_SHA_1 0x00000220 +#define CKM_AES_ECB 0x00001081 +#define CKM_AES_CBC 0x00001082 + +/* + * General Purpose Ioctls + */ + +typedef struct fl_mechs_threshold { + int mech_type; + uint32_t mech_threshold; +} fl_mechs_threshold_t; + +typedef struct crypto_function_list { + boolean_t fl_digest_init; + boolean_t fl_digest; + boolean_t fl_digest_update; + boolean_t fl_digest_key; + boolean_t fl_digest_final; + + boolean_t fl_encrypt_init; + boolean_t fl_encrypt; + boolean_t fl_encrypt_update; + boolean_t fl_encrypt_final; + + boolean_t fl_decrypt_init; + boolean_t fl_decrypt; + boolean_t fl_decrypt_update; + boolean_t fl_decrypt_final; + + boolean_t fl_mac_init; + boolean_t fl_mac; + boolean_t fl_mac_update; + boolean_t fl_mac_final; + + boolean_t fl_sign_init; + boolean_t fl_sign; + boolean_t fl_sign_update; + boolean_t fl_sign_final; + boolean_t fl_sign_recover_init; + boolean_t fl_sign_recover; + + boolean_t fl_verify_init; + boolean_t fl_verify; + boolean_t fl_verify_update; + boolean_t fl_verify_final; + boolean_t fl_verify_recover_init; + boolean_t fl_verify_recover; + + boolean_t fl_digest_encrypt_update; + boolean_t fl_decrypt_digest_update; + boolean_t fl_sign_encrypt_update; + boolean_t fl_decrypt_verify_update; + + boolean_t fl_seed_random; + boolean_t fl_generate_random; + + boolean_t fl_session_open; + boolean_t fl_session_close; + boolean_t fl_session_login; + boolean_t fl_session_logout; + + boolean_t fl_object_create; + boolean_t fl_object_copy; + boolean_t fl_object_destroy; + boolean_t fl_object_get_size; + boolean_t fl_object_get_attribute_value; + boolean_t fl_object_set_attribute_value; + boolean_t fl_object_find_init; + boolean_t fl_object_find; + boolean_t fl_object_find_final; + + boolean_t fl_key_generate; + boolean_t fl_key_generate_pair; + boolean_t fl_key_wrap; + boolean_t fl_key_unwrap; + boolean_t fl_key_derive; + + boolean_t fl_init_token; + boolean_t fl_init_pin; + boolean_t fl_set_pin; + + boolean_t prov_is_limited; + uint32_t prov_hash_threshold; + uint32_t prov_hash_limit; + + int total_threshold_count; + fl_mechs_threshold_t fl_threshold[MAX_NUM_THRESHOLD]; +} crypto_function_list_t; + +typedef struct crypto_get_function_list { + uint_t fl_return_value; + crypto_provider_id_t fl_provider_id; + crypto_function_list_t fl_list; +} crypto_get_function_list_t; + +typedef struct crypto_get_mechanism_number { + uint_t pn_return_value; + caddr_t pn_mechanism_string; + size_t pn_mechanism_len; + crypto_mech_type_t pn_internal_number; +} crypto_get_mechanism_number_t; + +#ifdef _KERNEL +#ifdef _SYSCALL32 + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct crypto_get_mechanism_number32 { + uint32_t pn_return_value; + caddr32_t pn_mechanism_string; + size32_t pn_mechanism_len; + crypto_mech_type_t pn_internal_number; +} crypto_get_mechanism_number32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +#endif /* _SYSCALL32 */ +#endif /* _KERNEL */ + +#define CRYPTO_GET_FUNCTION_LIST CRYPTO(20) +#define CRYPTO_GET_MECHANISM_NUMBER CRYPTO(21) + +/* + * Session Ioctls + */ + +typedef uint32_t crypto_flags_t; + +typedef struct crypto_open_session { + uint_t os_return_value; + crypto_session_id_t os_session; + crypto_flags_t os_flags; + crypto_provider_id_t os_provider_id; +} crypto_open_session_t; + +typedef struct crypto_close_session { + uint_t cs_return_value; + crypto_session_id_t cs_session; +} crypto_close_session_t; + +typedef struct crypto_close_all_sessions { + uint_t as_return_value; + crypto_provider_id_t as_provider_id; +} crypto_close_all_sessions_t; + +#define CRYPTO_OPEN_SESSION CRYPTO(30) +#define CRYPTO_CLOSE_SESSION CRYPTO(31) +#define CRYPTO_CLOSE_ALL_SESSIONS CRYPTO(32) + +/* + * Login Ioctls + */ +typedef struct crypto_login { + uint_t co_return_value; + crypto_session_id_t co_session; + uint_t co_user_type; + uint_t co_pin_len; + caddr_t co_pin; +} crypto_login_t; + +typedef struct crypto_logout { + uint_t cl_return_value; + crypto_session_id_t cl_session; +} crypto_logout_t; + +#ifdef _KERNEL +#ifdef _SYSCALL32 + +typedef struct crypto_login32 { + uint32_t co_return_value; + crypto_session_id_t co_session; + uint32_t co_user_type; + uint32_t co_pin_len; + caddr32_t co_pin; +} crypto_login32_t; + +typedef struct crypto_logout32 { + uint32_t cl_return_value; + crypto_session_id_t cl_session; +} crypto_logout32_t; + +#endif /* _SYSCALL32 */ +#endif /* _KERNEL */ + +#define CRYPTO_LOGIN CRYPTO(40) +#define CRYPTO_LOGOUT CRYPTO(41) + +/* flag for encrypt and decrypt operations */ +#define CRYPTO_INPLACE_OPERATION 0x00000001 + +/* + * Cryptographic Ioctls + */ +typedef struct crypto_encrypt { + uint_t ce_return_value; + crypto_session_id_t ce_session; + size_t ce_datalen; + caddr_t ce_databuf; + size_t ce_encrlen; + caddr_t ce_encrbuf; + uint_t ce_flags; +} crypto_encrypt_t; + +typedef struct crypto_encrypt_init { + uint_t ei_return_value; + crypto_session_id_t ei_session; + crypto_mechanism_t ei_mech; + crypto_key_t ei_key; +} crypto_encrypt_init_t; + +typedef struct crypto_encrypt_update { + uint_t eu_return_value; + crypto_session_id_t eu_session; + size_t eu_datalen; + caddr_t eu_databuf; + size_t eu_encrlen; + caddr_t eu_encrbuf; +} crypto_encrypt_update_t; + +typedef struct crypto_encrypt_final { + uint_t ef_return_value; + crypto_session_id_t ef_session; + size_t ef_encrlen; + caddr_t ef_encrbuf; +} crypto_encrypt_final_t; + +typedef struct crypto_decrypt { + uint_t cd_return_value; + crypto_session_id_t cd_session; + size_t cd_encrlen; + caddr_t cd_encrbuf; + size_t cd_datalen; + caddr_t cd_databuf; + uint_t cd_flags; +} crypto_decrypt_t; + +typedef struct crypto_decrypt_init { + uint_t di_return_value; + crypto_session_id_t di_session; + crypto_mechanism_t di_mech; + crypto_key_t di_key; +} crypto_decrypt_init_t; + +typedef struct crypto_decrypt_update { + uint_t du_return_value; + crypto_session_id_t du_session; + size_t du_encrlen; + caddr_t du_encrbuf; + size_t du_datalen; + caddr_t du_databuf; +} crypto_decrypt_update_t; + +typedef struct crypto_decrypt_final { + uint_t df_return_value; + crypto_session_id_t df_session; + size_t df_datalen; + caddr_t df_databuf; +} crypto_decrypt_final_t; + +typedef struct crypto_digest { + uint_t cd_return_value; + crypto_session_id_t cd_session; + size_t cd_datalen; + caddr_t cd_databuf; + size_t cd_digestlen; + caddr_t cd_digestbuf; +} crypto_digest_t; + +typedef struct crypto_digest_init { + uint_t di_return_value; + crypto_session_id_t di_session; + crypto_mechanism_t di_mech; +} crypto_digest_init_t; + +typedef struct crypto_digest_update { + uint_t du_return_value; + crypto_session_id_t du_session; + size_t du_datalen; + caddr_t du_databuf; +} crypto_digest_update_t; + +typedef struct crypto_digest_key { + uint_t dk_return_value; + crypto_session_id_t dk_session; + crypto_key_t dk_key; +} crypto_digest_key_t; + +typedef struct crypto_digest_final { + uint_t df_return_value; + crypto_session_id_t df_session; + size_t df_digestlen; + caddr_t df_digestbuf; +} crypto_digest_final_t; + +typedef struct crypto_mac { + uint_t cm_return_value; + crypto_session_id_t cm_session; + size_t cm_datalen; + caddr_t cm_databuf; + size_t cm_maclen; + caddr_t cm_macbuf; +} crypto_mac_t; + +typedef struct crypto_mac_init { + uint_t mi_return_value; + crypto_session_id_t mi_session; + crypto_mechanism_t mi_mech; + crypto_key_t mi_key; +} crypto_mac_init_t; + +typedef struct crypto_mac_update { + uint_t mu_return_value; + crypto_session_id_t mu_session; + size_t mu_datalen; + caddr_t mu_databuf; +} crypto_mac_update_t; + +typedef struct crypto_mac_final { + uint_t mf_return_value; + crypto_session_id_t mf_session; + size_t mf_maclen; + caddr_t mf_macbuf; +} crypto_mac_final_t; + +typedef struct crypto_sign { + uint_t cs_return_value; + crypto_session_id_t cs_session; + size_t cs_datalen; + caddr_t cs_databuf; + size_t cs_signlen; + caddr_t cs_signbuf; +} crypto_sign_t; + +typedef struct crypto_sign_init { + uint_t si_return_value; + crypto_session_id_t si_session; + crypto_mechanism_t si_mech; + crypto_key_t si_key; +} crypto_sign_init_t; + +typedef struct crypto_sign_update { + uint_t su_return_value; + crypto_session_id_t su_session; + size_t su_datalen; + caddr_t su_databuf; +} crypto_sign_update_t; + +typedef struct crypto_sign_final { + uint_t sf_return_value; + crypto_session_id_t sf_session; + size_t sf_signlen; + caddr_t sf_signbuf; +} crypto_sign_final_t; + +typedef struct crypto_sign_recover_init { + uint_t ri_return_value; + crypto_session_id_t ri_session; + crypto_mechanism_t ri_mech; + crypto_key_t ri_key; +} crypto_sign_recover_init_t; + +typedef struct crypto_sign_recover { + uint_t sr_return_value; + crypto_session_id_t sr_session; + size_t sr_datalen; + caddr_t sr_databuf; + size_t sr_signlen; + caddr_t sr_signbuf; +} crypto_sign_recover_t; + +typedef struct crypto_verify { + uint_t cv_return_value; + crypto_session_id_t cv_session; + size_t cv_datalen; + caddr_t cv_databuf; + size_t cv_signlen; + caddr_t cv_signbuf; +} crypto_verify_t; + +typedef struct crypto_verify_init { + uint_t vi_return_value; + crypto_session_id_t vi_session; + crypto_mechanism_t vi_mech; + crypto_key_t vi_key; +} crypto_verify_init_t; + +typedef struct crypto_verify_update { + uint_t vu_return_value; + crypto_session_id_t vu_session; + size_t vu_datalen; + caddr_t vu_databuf; +} crypto_verify_update_t; + +typedef struct crypto_verify_final { + uint_t vf_return_value; + crypto_session_id_t vf_session; + size_t vf_signlen; + caddr_t vf_signbuf; +} crypto_verify_final_t; + +typedef struct crypto_verify_recover_init { + uint_t ri_return_value; + crypto_session_id_t ri_session; + crypto_mechanism_t ri_mech; + crypto_key_t ri_key; +} crypto_verify_recover_init_t; + +typedef struct crypto_verify_recover { + uint_t vr_return_value; + crypto_session_id_t vr_session; + size_t vr_signlen; + caddr_t vr_signbuf; + size_t vr_datalen; + caddr_t vr_databuf; +} crypto_verify_recover_t; + +typedef struct crypto_digest_encrypt_update { + uint_t eu_return_value; + crypto_session_id_t eu_session; + size_t eu_datalen; + caddr_t eu_databuf; + size_t eu_encrlen; + caddr_t eu_encrbuf; +} crypto_digest_encrypt_update_t; + +typedef struct crypto_decrypt_digest_update { + uint_t du_return_value; + crypto_session_id_t du_session; + size_t du_encrlen; + caddr_t du_encrbuf; + size_t du_datalen; + caddr_t du_databuf; +} crypto_decrypt_digest_update_t; + +typedef struct crypto_sign_encrypt_update { + uint_t eu_return_value; + crypto_session_id_t eu_session; + size_t eu_datalen; + caddr_t eu_databuf; + size_t eu_encrlen; + caddr_t eu_encrbuf; +} crypto_sign_encrypt_update_t; + +typedef struct crypto_decrypt_verify_update { + uint_t vu_return_value; + crypto_session_id_t vu_session; + size_t vu_encrlen; + caddr_t vu_encrbuf; + size_t vu_datalen; + caddr_t vu_databuf; +} crypto_decrypt_verify_update_t; + +#ifdef _KERNEL +#ifdef _SYSCALL32 + +typedef struct crypto_encrypt32 { + uint32_t ce_return_value; + crypto_session_id_t ce_session; + size32_t ce_datalen; + caddr32_t ce_databuf; + size32_t ce_encrlen; + caddr32_t ce_encrbuf; + uint32_t ce_flags; +} crypto_encrypt32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct crypto_encrypt_init32 { + uint32_t ei_return_value; + crypto_session_id_t ei_session; + crypto_mechanism32_t ei_mech; + crypto_key32_t ei_key; +} crypto_encrypt_init32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +typedef struct crypto_encrypt_update32 { + uint32_t eu_return_value; + crypto_session_id_t eu_session; + size32_t eu_datalen; + caddr32_t eu_databuf; + size32_t eu_encrlen; + caddr32_t eu_encrbuf; +} crypto_encrypt_update32_t; + +typedef struct crypto_encrypt_final32 { + uint32_t ef_return_value; + crypto_session_id_t ef_session; + size32_t ef_encrlen; + caddr32_t ef_encrbuf; +} crypto_encrypt_final32_t; + +typedef struct crypto_decrypt32 { + uint32_t cd_return_value; + crypto_session_id_t cd_session; + size32_t cd_encrlen; + caddr32_t cd_encrbuf; + size32_t cd_datalen; + caddr32_t cd_databuf; + uint32_t cd_flags; +} crypto_decrypt32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct crypto_decrypt_init32 { + uint32_t di_return_value; + crypto_session_id_t di_session; + crypto_mechanism32_t di_mech; + crypto_key32_t di_key; +} crypto_decrypt_init32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +typedef struct crypto_decrypt_update32 { + uint32_t du_return_value; + crypto_session_id_t du_session; + size32_t du_encrlen; + caddr32_t du_encrbuf; + size32_t du_datalen; + caddr32_t du_databuf; +} crypto_decrypt_update32_t; + +typedef struct crypto_decrypt_final32 { + uint32_t df_return_value; + crypto_session_id_t df_session; + size32_t df_datalen; + caddr32_t df_databuf; +} crypto_decrypt_final32_t; + +typedef struct crypto_digest32 { + uint32_t cd_return_value; + crypto_session_id_t cd_session; + size32_t cd_datalen; + caddr32_t cd_databuf; + size32_t cd_digestlen; + caddr32_t cd_digestbuf; +} crypto_digest32_t; + +typedef struct crypto_digest_init32 { + uint32_t di_return_value; + crypto_session_id_t di_session; + crypto_mechanism32_t di_mech; +} crypto_digest_init32_t; + +typedef struct crypto_digest_update32 { + uint32_t du_return_value; + crypto_session_id_t du_session; + size32_t du_datalen; + caddr32_t du_databuf; +} crypto_digest_update32_t; + +typedef struct crypto_digest_key32 { + uint32_t dk_return_value; + crypto_session_id_t dk_session; + crypto_key32_t dk_key; +} crypto_digest_key32_t; + +typedef struct crypto_digest_final32 { + uint32_t df_return_value; + crypto_session_id_t df_session; + size32_t df_digestlen; + caddr32_t df_digestbuf; +} crypto_digest_final32_t; + +typedef struct crypto_mac32 { + uint32_t cm_return_value; + crypto_session_id_t cm_session; + size32_t cm_datalen; + caddr32_t cm_databuf; + size32_t cm_maclen; + caddr32_t cm_macbuf; +} crypto_mac32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct crypto_mac_init32 { + uint32_t mi_return_value; + crypto_session_id_t mi_session; + crypto_mechanism32_t mi_mech; + crypto_key32_t mi_key; +} crypto_mac_init32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +typedef struct crypto_mac_update32 { + uint32_t mu_return_value; + crypto_session_id_t mu_session; + size32_t mu_datalen; + caddr32_t mu_databuf; +} crypto_mac_update32_t; + +typedef struct crypto_mac_final32 { + uint32_t mf_return_value; + crypto_session_id_t mf_session; + size32_t mf_maclen; + caddr32_t mf_macbuf; +} crypto_mac_final32_t; + +typedef struct crypto_sign32 { + uint32_t cs_return_value; + crypto_session_id_t cs_session; + size32_t cs_datalen; + caddr32_t cs_databuf; + size32_t cs_signlen; + caddr32_t cs_signbuf; +} crypto_sign32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct crypto_sign_init32 { + uint32_t si_return_value; + crypto_session_id_t si_session; + crypto_mechanism32_t si_mech; + crypto_key32_t si_key; +} crypto_sign_init32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +typedef struct crypto_sign_update32 { + uint32_t su_return_value; + crypto_session_id_t su_session; + size32_t su_datalen; + caddr32_t su_databuf; +} crypto_sign_update32_t; + +typedef struct crypto_sign_final32 { + uint32_t sf_return_value; + crypto_session_id_t sf_session; + size32_t sf_signlen; + caddr32_t sf_signbuf; +} crypto_sign_final32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct crypto_sign_recover_init32 { + uint32_t ri_return_value; + crypto_session_id_t ri_session; + crypto_mechanism32_t ri_mech; + crypto_key32_t ri_key; +} crypto_sign_recover_init32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +typedef struct crypto_sign_recover32 { + uint32_t sr_return_value; + crypto_session_id_t sr_session; + size32_t sr_datalen; + caddr32_t sr_databuf; + size32_t sr_signlen; + caddr32_t sr_signbuf; +} crypto_sign_recover32_t; + +typedef struct crypto_verify32 { + uint32_t cv_return_value; + crypto_session_id_t cv_session; + size32_t cv_datalen; + caddr32_t cv_databuf; + size32_t cv_signlen; + caddr32_t cv_signbuf; +} crypto_verify32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct crypto_verify_init32 { + uint32_t vi_return_value; + crypto_session_id_t vi_session; + crypto_mechanism32_t vi_mech; + crypto_key32_t vi_key; +} crypto_verify_init32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +typedef struct crypto_verify_update32 { + uint32_t vu_return_value; + crypto_session_id_t vu_session; + size32_t vu_datalen; + caddr32_t vu_databuf; +} crypto_verify_update32_t; + +typedef struct crypto_verify_final32 { + uint32_t vf_return_value; + crypto_session_id_t vf_session; + size32_t vf_signlen; + caddr32_t vf_signbuf; +} crypto_verify_final32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct crypto_verify_recover_init32 { + uint32_t ri_return_value; + crypto_session_id_t ri_session; + crypto_mechanism32_t ri_mech; + crypto_key32_t ri_key; +} crypto_verify_recover_init32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +typedef struct crypto_verify_recover32 { + uint32_t vr_return_value; + crypto_session_id_t vr_session; + size32_t vr_signlen; + caddr32_t vr_signbuf; + size32_t vr_datalen; + caddr32_t vr_databuf; +} crypto_verify_recover32_t; + +typedef struct crypto_digest_encrypt_update32 { + uint32_t eu_return_value; + crypto_session_id_t eu_session; + size32_t eu_datalen; + caddr32_t eu_databuf; + size32_t eu_encrlen; + caddr32_t eu_encrbuf; +} crypto_digest_encrypt_update32_t; + +typedef struct crypto_decrypt_digest_update32 { + uint32_t du_return_value; + crypto_session_id_t du_session; + size32_t du_encrlen; + caddr32_t du_encrbuf; + size32_t du_datalen; + caddr32_t du_databuf; +} crypto_decrypt_digest_update32_t; + +typedef struct crypto_sign_encrypt_update32 { + uint32_t eu_return_value; + crypto_session_id_t eu_session; + size32_t eu_datalen; + caddr32_t eu_databuf; + size32_t eu_encrlen; + caddr32_t eu_encrbuf; +} crypto_sign_encrypt_update32_t; + +typedef struct crypto_decrypt_verify_update32 { + uint32_t vu_return_value; + crypto_session_id_t vu_session; + size32_t vu_encrlen; + caddr32_t vu_encrbuf; + size32_t vu_datalen; + caddr32_t vu_databuf; +} crypto_decrypt_verify_update32_t; + +#endif /* _SYSCALL32 */ +#endif /* _KERNEL */ + +#define CRYPTO_ENCRYPT CRYPTO(50) +#define CRYPTO_ENCRYPT_INIT CRYPTO(51) +#define CRYPTO_ENCRYPT_UPDATE CRYPTO(52) +#define CRYPTO_ENCRYPT_FINAL CRYPTO(53) +#define CRYPTO_DECRYPT CRYPTO(54) +#define CRYPTO_DECRYPT_INIT CRYPTO(55) +#define CRYPTO_DECRYPT_UPDATE CRYPTO(56) +#define CRYPTO_DECRYPT_FINAL CRYPTO(57) + +#define CRYPTO_DIGEST CRYPTO(58) +#define CRYPTO_DIGEST_INIT CRYPTO(59) +#define CRYPTO_DIGEST_UPDATE CRYPTO(60) +#define CRYPTO_DIGEST_KEY CRYPTO(61) +#define CRYPTO_DIGEST_FINAL CRYPTO(62) +#define CRYPTO_MAC CRYPTO(63) +#define CRYPTO_MAC_INIT CRYPTO(64) +#define CRYPTO_MAC_UPDATE CRYPTO(65) +#define CRYPTO_MAC_FINAL CRYPTO(66) + +#define CRYPTO_SIGN CRYPTO(67) +#define CRYPTO_SIGN_INIT CRYPTO(68) +#define CRYPTO_SIGN_UPDATE CRYPTO(69) +#define CRYPTO_SIGN_FINAL CRYPTO(70) +#define CRYPTO_SIGN_RECOVER_INIT CRYPTO(71) +#define CRYPTO_SIGN_RECOVER CRYPTO(72) +#define CRYPTO_VERIFY CRYPTO(73) +#define CRYPTO_VERIFY_INIT CRYPTO(74) +#define CRYPTO_VERIFY_UPDATE CRYPTO(75) +#define CRYPTO_VERIFY_FINAL CRYPTO(76) +#define CRYPTO_VERIFY_RECOVER_INIT CRYPTO(77) +#define CRYPTO_VERIFY_RECOVER CRYPTO(78) + +#define CRYPTO_DIGEST_ENCRYPT_UPDATE CRYPTO(79) +#define CRYPTO_DECRYPT_DIGEST_UPDATE CRYPTO(80) +#define CRYPTO_SIGN_ENCRYPT_UPDATE CRYPTO(81) +#define CRYPTO_DECRYPT_VERIFY_UPDATE CRYPTO(82) + +/* + * Random Number Ioctls + */ +typedef struct crypto_seed_random { + uint_t sr_return_value; + crypto_session_id_t sr_session; + size_t sr_seedlen; + caddr_t sr_seedbuf; +} crypto_seed_random_t; + +typedef struct crypto_generate_random { + uint_t gr_return_value; + crypto_session_id_t gr_session; + caddr_t gr_buf; + size_t gr_buflen; +} crypto_generate_random_t; + +#ifdef _KERNEL +#ifdef _SYSCALL32 + +typedef struct crypto_seed_random32 { + uint32_t sr_return_value; + crypto_session_id_t sr_session; + size32_t sr_seedlen; + caddr32_t sr_seedbuf; +} crypto_seed_random32_t; + +typedef struct crypto_generate_random32 { + uint32_t gr_return_value; + crypto_session_id_t gr_session; + caddr32_t gr_buf; + size32_t gr_buflen; +} crypto_generate_random32_t; + +#endif /* _SYSCALL32 */ +#endif /* _KERNEL */ + +#define CRYPTO_SEED_RANDOM CRYPTO(90) +#define CRYPTO_GENERATE_RANDOM CRYPTO(91) + +/* + * Object Management Ioctls + */ +typedef struct crypto_object_create { + uint_t oc_return_value; + crypto_session_id_t oc_session; + crypto_object_id_t oc_handle; + uint_t oc_count; + caddr_t oc_attributes; +} crypto_object_create_t; + +typedef struct crypto_object_copy { + uint_t oc_return_value; + crypto_session_id_t oc_session; + crypto_object_id_t oc_handle; + crypto_object_id_t oc_new_handle; + uint_t oc_count; + caddr_t oc_new_attributes; +} crypto_object_copy_t; + +typedef struct crypto_object_destroy { + uint_t od_return_value; + crypto_session_id_t od_session; + crypto_object_id_t od_handle; +} crypto_object_destroy_t; + +typedef struct crypto_object_get_attribute_value { + uint_t og_return_value; + crypto_session_id_t og_session; + crypto_object_id_t og_handle; + uint_t og_count; + caddr_t og_attributes; +} crypto_object_get_attribute_value_t; + +typedef struct crypto_object_get_size { + uint_t gs_return_value; + crypto_session_id_t gs_session; + crypto_object_id_t gs_handle; + size_t gs_size; +} crypto_object_get_size_t; + +typedef struct crypto_object_set_attribute_value { + uint_t sa_return_value; + crypto_session_id_t sa_session; + crypto_object_id_t sa_handle; + uint_t sa_count; + caddr_t sa_attributes; +} crypto_object_set_attribute_value_t; + +typedef struct crypto_object_find_init { + uint_t fi_return_value; + crypto_session_id_t fi_session; + uint_t fi_count; + caddr_t fi_attributes; +} crypto_object_find_init_t; + +typedef struct crypto_object_find_update { + uint_t fu_return_value; + crypto_session_id_t fu_session; + uint_t fu_max_count; + uint_t fu_count; + caddr_t fu_handles; +} crypto_object_find_update_t; + +typedef struct crypto_object_find_final { + uint_t ff_return_value; + crypto_session_id_t ff_session; +} crypto_object_find_final_t; + +#ifdef _KERNEL +#ifdef _SYSCALL32 + +typedef struct crypto_object_create32 { + uint32_t oc_return_value; + crypto_session_id_t oc_session; + crypto_object_id_t oc_handle; + uint32_t oc_count; + caddr32_t oc_attributes; +} crypto_object_create32_t; + +typedef struct crypto_object_copy32 { + uint32_t oc_return_value; + crypto_session_id_t oc_session; + crypto_object_id_t oc_handle; + crypto_object_id_t oc_new_handle; + uint32_t oc_count; + caddr32_t oc_new_attributes; +} crypto_object_copy32_t; + +typedef struct crypto_object_destroy32 { + uint32_t od_return_value; + crypto_session_id_t od_session; + crypto_object_id_t od_handle; +} crypto_object_destroy32_t; + +typedef struct crypto_object_get_attribute_value32 { + uint32_t og_return_value; + crypto_session_id_t og_session; + crypto_object_id_t og_handle; + uint32_t og_count; + caddr32_t og_attributes; +} crypto_object_get_attribute_value32_t; + +typedef struct crypto_object_get_size32 { + uint32_t gs_return_value; + crypto_session_id_t gs_session; + crypto_object_id_t gs_handle; + size32_t gs_size; +} crypto_object_get_size32_t; + +typedef struct crypto_object_set_attribute_value32 { + uint32_t sa_return_value; + crypto_session_id_t sa_session; + crypto_object_id_t sa_handle; + uint32_t sa_count; + caddr32_t sa_attributes; +} crypto_object_set_attribute_value32_t; + +typedef struct crypto_object_find_init32 { + uint32_t fi_return_value; + crypto_session_id_t fi_session; + uint32_t fi_count; + caddr32_t fi_attributes; +} crypto_object_find_init32_t; + +typedef struct crypto_object_find_update32 { + uint32_t fu_return_value; + crypto_session_id_t fu_session; + uint32_t fu_max_count; + uint32_t fu_count; + caddr32_t fu_handles; +} crypto_object_find_update32_t; + +typedef struct crypto_object_find_final32 { + uint32_t ff_return_value; + crypto_session_id_t ff_session; +} crypto_object_find_final32_t; + +#endif /* _SYSCALL32 */ +#endif /* _KERNEL */ + +#define CRYPTO_OBJECT_CREATE CRYPTO(100) +#define CRYPTO_OBJECT_COPY CRYPTO(101) +#define CRYPTO_OBJECT_DESTROY CRYPTO(102) +#define CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE CRYPTO(103) +#define CRYPTO_OBJECT_GET_SIZE CRYPTO(104) +#define CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE CRYPTO(105) +#define CRYPTO_OBJECT_FIND_INIT CRYPTO(106) +#define CRYPTO_OBJECT_FIND_UPDATE CRYPTO(107) +#define CRYPTO_OBJECT_FIND_FINAL CRYPTO(108) + +/* + * Key Generation Ioctls + */ +typedef struct crypto_object_generate_key { + uint_t gk_return_value; + crypto_session_id_t gk_session; + crypto_object_id_t gk_handle; + crypto_mechanism_t gk_mechanism; + uint_t gk_count; + caddr_t gk_attributes; +} crypto_object_generate_key_t; + +typedef struct crypto_object_generate_key_pair { + uint_t kp_return_value; + crypto_session_id_t kp_session; + crypto_object_id_t kp_public_handle; + crypto_object_id_t kp_private_handle; + uint_t kp_public_count; + uint_t kp_private_count; + caddr_t kp_public_attributes; + caddr_t kp_private_attributes; + crypto_mechanism_t kp_mechanism; +} crypto_object_generate_key_pair_t; + +typedef struct crypto_object_wrap_key { + uint_t wk_return_value; + crypto_session_id_t wk_session; + crypto_mechanism_t wk_mechanism; + crypto_key_t wk_wrapping_key; + crypto_object_id_t wk_object_handle; + size_t wk_wrapped_key_len; + caddr_t wk_wrapped_key; +} crypto_object_wrap_key_t; + +typedef struct crypto_object_unwrap_key { + uint_t uk_return_value; + crypto_session_id_t uk_session; + crypto_mechanism_t uk_mechanism; + crypto_key_t uk_unwrapping_key; + crypto_object_id_t uk_object_handle; + size_t uk_wrapped_key_len; + caddr_t uk_wrapped_key; + uint_t uk_count; + caddr_t uk_attributes; +} crypto_object_unwrap_key_t; + +typedef struct crypto_derive_key { + uint_t dk_return_value; + crypto_session_id_t dk_session; + crypto_mechanism_t dk_mechanism; + crypto_key_t dk_base_key; + crypto_object_id_t dk_object_handle; + uint_t dk_count; + caddr_t dk_attributes; +} crypto_derive_key_t; + +#ifdef _KERNEL +#ifdef _SYSCALL32 + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct crypto_object_generate_key32 { + uint32_t gk_return_value; + crypto_session_id_t gk_session; + crypto_object_id_t gk_handle; + crypto_mechanism32_t gk_mechanism; + uint32_t gk_count; + caddr32_t gk_attributes; +} crypto_object_generate_key32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +typedef struct crypto_object_generate_key_pair32 { + uint32_t kp_return_value; + crypto_session_id_t kp_session; + crypto_object_id_t kp_public_handle; + crypto_object_id_t kp_private_handle; + uint32_t kp_public_count; + uint32_t kp_private_count; + caddr32_t kp_public_attributes; + caddr32_t kp_private_attributes; + crypto_mechanism32_t kp_mechanism; +} crypto_object_generate_key_pair32_t; + +typedef struct crypto_object_wrap_key32 { + uint32_t wk_return_value; + crypto_session_id_t wk_session; + crypto_mechanism32_t wk_mechanism; + crypto_key32_t wk_wrapping_key; + crypto_object_id_t wk_object_handle; + size32_t wk_wrapped_key_len; + caddr32_t wk_wrapped_key; +} crypto_object_wrap_key32_t; + +typedef struct crypto_object_unwrap_key32 { + uint32_t uk_return_value; + crypto_session_id_t uk_session; + crypto_mechanism32_t uk_mechanism; + crypto_key32_t uk_unwrapping_key; + crypto_object_id_t uk_object_handle; + size32_t uk_wrapped_key_len; + caddr32_t uk_wrapped_key; + uint32_t uk_count; + caddr32_t uk_attributes; +} crypto_object_unwrap_key32_t; + +typedef struct crypto_derive_key32 { + uint32_t dk_return_value; + crypto_session_id_t dk_session; + crypto_mechanism32_t dk_mechanism; + crypto_key32_t dk_base_key; + crypto_object_id_t dk_object_handle; + uint32_t dk_count; + caddr32_t dk_attributes; +} crypto_derive_key32_t; + +#endif /* _SYSCALL32 */ +#endif /* _KERNEL */ + +#define CRYPTO_GENERATE_KEY CRYPTO(110) +#define CRYPTO_GENERATE_KEY_PAIR CRYPTO(111) +#define CRYPTO_WRAP_KEY CRYPTO(112) +#define CRYPTO_UNWRAP_KEY CRYPTO(113) +#define CRYPTO_DERIVE_KEY CRYPTO(114) + +/* + * Provider Management Ioctls + */ + +typedef struct crypto_get_provider_list { + uint_t pl_return_value; + uint_t pl_count; + crypto_provider_entry_t pl_list[1]; +} crypto_get_provider_list_t; + +typedef struct crypto_provider_data { + uchar_t pd_prov_desc[CRYPTO_PROVIDER_DESCR_MAX_LEN]; + uchar_t pd_label[CRYPTO_EXT_SIZE_LABEL]; + uchar_t pd_manufacturerID[CRYPTO_EXT_SIZE_MANUF]; + uchar_t pd_model[CRYPTO_EXT_SIZE_MODEL]; + uchar_t pd_serial_number[CRYPTO_EXT_SIZE_SERIAL]; + ulong_t pd_flags; + ulong_t pd_max_session_count; + ulong_t pd_session_count; + ulong_t pd_max_rw_session_count; + ulong_t pd_rw_session_count; + ulong_t pd_max_pin_len; + ulong_t pd_min_pin_len; + ulong_t pd_total_public_memory; + ulong_t pd_free_public_memory; + ulong_t pd_total_private_memory; + ulong_t pd_free_private_memory; + crypto_version_t pd_hardware_version; + crypto_version_t pd_firmware_version; + uchar_t pd_time[CRYPTO_EXT_SIZE_TIME]; +} crypto_provider_data_t; + +typedef struct crypto_get_provider_info { + uint_t gi_return_value; + crypto_provider_id_t gi_provider_id; + crypto_provider_data_t gi_provider_data; +} crypto_get_provider_info_t; + +typedef struct crypto_get_provider_mechanisms { + uint_t pm_return_value; + crypto_provider_id_t pm_provider_id; + uint_t pm_count; + crypto_mech_name_t pm_list[1]; +} crypto_get_provider_mechanisms_t; + +typedef struct crypto_get_provider_mechanism_info { + uint_t mi_return_value; + crypto_provider_id_t mi_provider_id; + crypto_mech_name_t mi_mechanism_name; + uint32_t mi_min_key_size; + uint32_t mi_max_key_size; + uint32_t mi_flags; +} crypto_get_provider_mechanism_info_t; + +typedef struct crypto_init_token { + uint_t it_return_value; + crypto_provider_id_t it_provider_id; + caddr_t it_pin; + size_t it_pin_len; + caddr_t it_label; +} crypto_init_token_t; + +typedef struct crypto_init_pin { + uint_t ip_return_value; + crypto_session_id_t ip_session; + caddr_t ip_pin; + size_t ip_pin_len; +} crypto_init_pin_t; + +typedef struct crypto_set_pin { + uint_t sp_return_value; + crypto_session_id_t sp_session; + caddr_t sp_old_pin; + size_t sp_old_len; + caddr_t sp_new_pin; + size_t sp_new_len; +} crypto_set_pin_t; + +#ifdef _KERNEL +#ifdef _SYSCALL32 + +typedef struct crypto_get_provider_list32 { + uint32_t pl_return_value; + uint32_t pl_count; + crypto_provider_entry_t pl_list[1]; +} crypto_get_provider_list32_t; + +typedef struct crypto_version32 { + uchar_t cv_major; + uchar_t cv_minor; +} crypto_version32_t; + +typedef struct crypto_provider_data32 { + uchar_t pd_prov_desc[CRYPTO_PROVIDER_DESCR_MAX_LEN]; + uchar_t pd_label[CRYPTO_EXT_SIZE_LABEL]; + uchar_t pd_manufacturerID[CRYPTO_EXT_SIZE_MANUF]; + uchar_t pd_model[CRYPTO_EXT_SIZE_MODEL]; + uchar_t pd_serial_number[CRYPTO_EXT_SIZE_SERIAL]; + uint32_t pd_flags; + uint32_t pd_max_session_count; + uint32_t pd_session_count; + uint32_t pd_max_rw_session_count; + uint32_t pd_rw_session_count; + uint32_t pd_max_pin_len; + uint32_t pd_min_pin_len; + uint32_t pd_total_public_memory; + uint32_t pd_free_public_memory; + uint32_t pd_total_private_memory; + uint32_t pd_free_private_memory; + crypto_version32_t pd_hardware_version; + crypto_version32_t pd_firmware_version; + uchar_t pd_time[CRYPTO_EXT_SIZE_TIME]; +} crypto_provider_data32_t; + +typedef struct crypto_get_provider_info32 { + uint32_t gi_return_value; + crypto_provider_id_t gi_provider_id; + crypto_provider_data32_t gi_provider_data; +} crypto_get_provider_info32_t; + +typedef struct crypto_get_provider_mechanisms32 { + uint32_t pm_return_value; + crypto_provider_id_t pm_provider_id; + uint32_t pm_count; + crypto_mech_name_t pm_list[1]; +} crypto_get_provider_mechanisms32_t; + +typedef struct crypto_init_token32 { + uint32_t it_return_value; + crypto_provider_id_t it_provider_id; + caddr32_t it_pin; + size32_t it_pin_len; + caddr32_t it_label; +} crypto_init_token32_t; + +typedef struct crypto_init_pin32 { + uint32_t ip_return_value; + crypto_session_id_t ip_session; + caddr32_t ip_pin; + size32_t ip_pin_len; +} crypto_init_pin32_t; + +typedef struct crypto_set_pin32 { + uint32_t sp_return_value; + crypto_session_id_t sp_session; + caddr32_t sp_old_pin; + size32_t sp_old_len; + caddr32_t sp_new_pin; + size32_t sp_new_len; +} crypto_set_pin32_t; + +#endif /* _SYSCALL32 */ +#endif /* _KERNEL */ + +#define CRYPTO_GET_PROVIDER_LIST CRYPTO(120) +#define CRYPTO_GET_PROVIDER_INFO CRYPTO(121) +#define CRYPTO_GET_PROVIDER_MECHANISMS CRYPTO(122) +#define CRYPTO_GET_PROVIDER_MECHANISM_INFO CRYPTO(123) +#define CRYPTO_INIT_TOKEN CRYPTO(124) +#define CRYPTO_INIT_PIN CRYPTO(125) +#define CRYPTO_SET_PIN CRYPTO(126) + +/* + * No (Key) Store Key Generation Ioctls + */ +typedef struct crypto_nostore_generate_key { + uint_t ngk_return_value; + crypto_session_id_t ngk_session; + crypto_mechanism_t ngk_mechanism; + uint_t ngk_in_count; + uint_t ngk_out_count; + caddr_t ngk_in_attributes; + caddr_t ngk_out_attributes; +} crypto_nostore_generate_key_t; + +typedef struct crypto_nostore_generate_key_pair { + uint_t nkp_return_value; + crypto_session_id_t nkp_session; + uint_t nkp_in_public_count; + uint_t nkp_in_private_count; + uint_t nkp_out_public_count; + uint_t nkp_out_private_count; + caddr_t nkp_in_public_attributes; + caddr_t nkp_in_private_attributes; + caddr_t nkp_out_public_attributes; + caddr_t nkp_out_private_attributes; + crypto_mechanism_t nkp_mechanism; +} crypto_nostore_generate_key_pair_t; + +typedef struct crypto_nostore_derive_key { + uint_t ndk_return_value; + crypto_session_id_t ndk_session; + crypto_mechanism_t ndk_mechanism; + crypto_key_t ndk_base_key; + uint_t ndk_in_count; + uint_t ndk_out_count; + caddr_t ndk_in_attributes; + caddr_t ndk_out_attributes; +} crypto_nostore_derive_key_t; + +#ifdef _KERNEL +#ifdef _SYSCALL32 + +typedef struct crypto_nostore_generate_key32 { + uint32_t ngk_return_value; + crypto_session_id_t ngk_session; + crypto_mechanism32_t ngk_mechanism; + uint32_t ngk_in_count; + uint32_t ngk_out_count; + caddr32_t ngk_in_attributes; + caddr32_t ngk_out_attributes; +} crypto_nostore_generate_key32_t; + +typedef struct crypto_nostore_generate_key_pair32 { + uint32_t nkp_return_value; + crypto_session_id_t nkp_session; + uint32_t nkp_in_public_count; + uint32_t nkp_in_private_count; + uint32_t nkp_out_public_count; + uint32_t nkp_out_private_count; + caddr32_t nkp_in_public_attributes; + caddr32_t nkp_in_private_attributes; + caddr32_t nkp_out_public_attributes; + caddr32_t nkp_out_private_attributes; + crypto_mechanism32_t nkp_mechanism; +} crypto_nostore_generate_key_pair32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct crypto_nostore_derive_key32 { + uint32_t ndk_return_value; + crypto_session_id_t ndk_session; + crypto_mechanism32_t ndk_mechanism; + crypto_key32_t ndk_base_key; + uint32_t ndk_in_count; + uint32_t ndk_out_count; + caddr32_t ndk_in_attributes; + caddr32_t ndk_out_attributes; +} crypto_nostore_derive_key32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +#endif /* _SYSCALL32 */ +#endif /* _KERNEL */ + +#define CRYPTO_NOSTORE_GENERATE_KEY CRYPTO(127) +#define CRYPTO_NOSTORE_GENERATE_KEY_PAIR CRYPTO(128) +#define CRYPTO_NOSTORE_DERIVE_KEY CRYPTO(129) + +/* + * Mechanism Ioctls + */ + +typedef struct crypto_get_mechanism_list { + uint_t ml_return_value; + uint_t ml_count; + crypto_mech_name_t ml_list[1]; +} crypto_get_mechanism_list_t; + +typedef struct crypto_get_all_mechanism_info { + uint_t mi_return_value; + crypto_mech_name_t mi_mechanism_name; + uint_t mi_count; + crypto_mechanism_info_t mi_list[1]; +} crypto_get_all_mechanism_info_t; + +#ifdef _KERNEL +#ifdef _SYSCALL32 + +typedef struct crypto_get_mechanism_list32 { + uint32_t ml_return_value; + uint32_t ml_count; + crypto_mech_name_t ml_list[1]; +} crypto_get_mechanism_list32_t; + +typedef struct crypto_get_all_mechanism_info32 { + uint32_t mi_return_value; + crypto_mech_name_t mi_mechanism_name; + uint32_t mi_count; + crypto_mechanism_info32_t mi_list[1]; +} crypto_get_all_mechanism_info32_t; + +#endif /* _SYSCALL32 */ +#endif /* _KERNEL */ + +#define CRYPTO_GET_MECHANISM_LIST CRYPTO(140) +#define CRYPTO_GET_ALL_MECHANISM_INFO CRYPTO(141) + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_CRYPTO_IOCTL_H */ diff --git a/module/icp/include/sys/crypto/ioctladmin.h b/module/icp/include/sys/crypto/ioctladmin.h new file mode 100644 index 000000000..24babd775 --- /dev/null +++ b/module/icp/include/sys/crypto/ioctladmin.h @@ -0,0 +1,136 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_CRYPTO_IOCTLADMIN_H +#define _SYS_CRYPTO_IOCTLADMIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/zfs_context.h> +#include <sys/crypto/common.h> + +#define ADMIN_IOCTL_DEVICE "/dev/cryptoadm" + +#define CRYPTOADMIN(x) (('y' << 8) | (x)) + +/* + * Administrative IOCTLs + */ + +typedef struct crypto_get_dev_list { + uint_t dl_return_value; + uint_t dl_dev_count; + crypto_dev_list_entry_t dl_devs[1]; +} crypto_get_dev_list_t; + +typedef struct crypto_get_soft_list { + uint_t sl_return_value; + uint_t sl_soft_count; + size_t sl_soft_len; + caddr_t sl_soft_names; +} crypto_get_soft_list_t; + +typedef struct crypto_get_dev_info { + uint_t di_return_value; + char di_dev_name[MAXNAMELEN]; + uint_t di_dev_instance; + uint_t di_count; + crypto_mech_name_t di_list[1]; +} crypto_get_dev_info_t; + +typedef struct crypto_get_soft_info { + uint_t si_return_value; + char si_name[MAXNAMELEN]; + uint_t si_count; + crypto_mech_name_t si_list[1]; +} crypto_get_soft_info_t; + +typedef struct crypto_load_dev_disabled { + uint_t dd_return_value; + char dd_dev_name[MAXNAMELEN]; + uint_t dd_dev_instance; + uint_t dd_count; + crypto_mech_name_t dd_list[1]; +} crypto_load_dev_disabled_t; + +typedef struct crypto_load_soft_disabled { + uint_t sd_return_value; + char sd_name[MAXNAMELEN]; + uint_t sd_count; + crypto_mech_name_t sd_list[1]; +} crypto_load_soft_disabled_t; + +typedef struct crypto_unload_soft_module { + uint_t sm_return_value; + char sm_name[MAXNAMELEN]; +} crypto_unload_soft_module_t; + +typedef struct crypto_load_soft_config { + uint_t sc_return_value; + char sc_name[MAXNAMELEN]; + uint_t sc_count; + crypto_mech_name_t sc_list[1]; +} crypto_load_soft_config_t; + +typedef struct crypto_load_door { + uint_t ld_return_value; + uint_t ld_did; +} crypto_load_door_t; + +#ifdef _KERNEL +#ifdef _SYSCALL32 + +typedef struct crypto_get_soft_list32 { + uint32_t sl_return_value; + uint32_t sl_soft_count; + size32_t sl_soft_len; + caddr32_t sl_soft_names; +} crypto_get_soft_list32_t; + +#endif /* _SYSCALL32 */ +#endif /* _KERNEL */ + +#define CRYPTO_GET_VERSION CRYPTOADMIN(1) +#define CRYPTO_GET_DEV_LIST CRYPTOADMIN(2) +#define CRYPTO_GET_SOFT_LIST CRYPTOADMIN(3) +#define CRYPTO_GET_DEV_INFO CRYPTOADMIN(4) +#define CRYPTO_GET_SOFT_INFO CRYPTOADMIN(5) +#define CRYPTO_LOAD_DEV_DISABLED CRYPTOADMIN(8) +#define CRYPTO_LOAD_SOFT_DISABLED CRYPTOADMIN(9) +#define CRYPTO_UNLOAD_SOFT_MODULE CRYPTOADMIN(10) +#define CRYPTO_LOAD_SOFT_CONFIG CRYPTOADMIN(11) +#define CRYPTO_POOL_CREATE CRYPTOADMIN(12) +#define CRYPTO_POOL_WAIT CRYPTOADMIN(13) +#define CRYPTO_POOL_RUN CRYPTOADMIN(14) +#define CRYPTO_LOAD_DOOR CRYPTOADMIN(15) + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_CRYPTO_IOCTLADMIN_H */ diff --git a/module/icp/include/sys/crypto/ops_impl.h b/module/icp/include/sys/crypto/ops_impl.h new file mode 100644 index 000000000..230d74b06 --- /dev/null +++ b/module/icp/include/sys/crypto/ops_impl.h @@ -0,0 +1,630 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_CRYPTO_OPS_IMPL_H +#define _SYS_CRYPTO_OPS_IMPL_H + +/* + * Scheduler internal structures. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/zfs_context.h> +#include <sys/crypto/api.h> +#include <sys/crypto/spi.h> +#include <sys/crypto/impl.h> +#include <sys/crypto/common.h> + +/* + * The parameters needed for each function group are batched + * in one structure. This is much simpler than having a + * separate structure for each function. + * + * In some cases, a field is generically named to keep the + * structure small. The comments indicate these cases. + */ +typedef struct kcf_digest_ops_params { + crypto_session_id_t do_sid; + crypto_mech_type_t do_framework_mechtype; + crypto_mechanism_t do_mech; + crypto_data_t *do_data; + crypto_data_t *do_digest; + crypto_key_t *do_digest_key; /* Argument for digest_key() */ +} kcf_digest_ops_params_t; + +typedef struct kcf_mac_ops_params { + crypto_session_id_t mo_sid; + crypto_mech_type_t mo_framework_mechtype; + crypto_mechanism_t mo_mech; + crypto_key_t *mo_key; + crypto_data_t *mo_data; + crypto_data_t *mo_mac; + crypto_spi_ctx_template_t mo_templ; +} kcf_mac_ops_params_t; + +typedef struct kcf_encrypt_ops_params { + crypto_session_id_t eo_sid; + crypto_mech_type_t eo_framework_mechtype; + crypto_mechanism_t eo_mech; + crypto_key_t *eo_key; + crypto_data_t *eo_plaintext; + crypto_data_t *eo_ciphertext; + crypto_spi_ctx_template_t eo_templ; +} kcf_encrypt_ops_params_t; + +typedef struct kcf_decrypt_ops_params { + crypto_session_id_t dop_sid; + crypto_mech_type_t dop_framework_mechtype; + crypto_mechanism_t dop_mech; + crypto_key_t *dop_key; + crypto_data_t *dop_ciphertext; + crypto_data_t *dop_plaintext; + crypto_spi_ctx_template_t dop_templ; +} kcf_decrypt_ops_params_t; + +typedef struct kcf_sign_ops_params { + crypto_session_id_t so_sid; + crypto_mech_type_t so_framework_mechtype; + crypto_mechanism_t so_mech; + crypto_key_t *so_key; + crypto_data_t *so_data; + crypto_data_t *so_signature; + crypto_spi_ctx_template_t so_templ; +} kcf_sign_ops_params_t; + +typedef struct kcf_verify_ops_params { + crypto_session_id_t vo_sid; + crypto_mech_type_t vo_framework_mechtype; + crypto_mechanism_t vo_mech; + crypto_key_t *vo_key; + crypto_data_t *vo_data; + crypto_data_t *vo_signature; + crypto_spi_ctx_template_t vo_templ; +} kcf_verify_ops_params_t; + +typedef struct kcf_encrypt_mac_ops_params { + crypto_session_id_t em_sid; + crypto_mech_type_t em_framework_encr_mechtype; + crypto_mechanism_t em_encr_mech; + crypto_key_t *em_encr_key; + crypto_mech_type_t em_framework_mac_mechtype; + crypto_mechanism_t em_mac_mech; + crypto_key_t *em_mac_key; + crypto_data_t *em_plaintext; + crypto_dual_data_t *em_ciphertext; + crypto_data_t *em_mac; + crypto_spi_ctx_template_t em_encr_templ; + crypto_spi_ctx_template_t em_mac_templ; +} kcf_encrypt_mac_ops_params_t; + +typedef struct kcf_mac_decrypt_ops_params { + crypto_session_id_t md_sid; + crypto_mech_type_t md_framework_mac_mechtype; + crypto_mechanism_t md_mac_mech; + crypto_key_t *md_mac_key; + crypto_mech_type_t md_framework_decr_mechtype; + crypto_mechanism_t md_decr_mech; + crypto_key_t *md_decr_key; + crypto_dual_data_t *md_ciphertext; + crypto_data_t *md_mac; + crypto_data_t *md_plaintext; + crypto_spi_ctx_template_t md_mac_templ; + crypto_spi_ctx_template_t md_decr_templ; +} kcf_mac_decrypt_ops_params_t; + +typedef struct kcf_random_number_ops_params { + crypto_session_id_t rn_sid; + uchar_t *rn_buf; + size_t rn_buflen; + uint_t rn_entropy_est; + uint32_t rn_flags; +} kcf_random_number_ops_params_t; + +/* + * so_pd is useful when the provider descriptor (pd) supplying the + * provider handle is different from the pd supplying the ops vector. + * This is the case for session open/close where so_pd can be the pd + * of a logical provider. The pd supplying the ops vector is passed + * as an argument to kcf_submit_request(). + */ +typedef struct kcf_session_ops_params { + crypto_session_id_t *so_sid_ptr; + crypto_session_id_t so_sid; + crypto_user_type_t so_user_type; + char *so_pin; + size_t so_pin_len; + kcf_provider_desc_t *so_pd; +} kcf_session_ops_params_t; + +typedef struct kcf_object_ops_params { + crypto_session_id_t oo_sid; + crypto_object_id_t oo_object_id; + crypto_object_attribute_t *oo_template; + uint_t oo_attribute_count; + crypto_object_id_t *oo_object_id_ptr; + size_t *oo_object_size; + void **oo_find_init_pp_ptr; + void *oo_find_pp; + uint_t oo_max_object_count; + uint_t *oo_object_count_ptr; +} kcf_object_ops_params_t; + +/* + * ko_key is used to encode wrapping key in key_wrap() and + * unwrapping key in key_unwrap(). ko_key_template and + * ko_key_attribute_count are used to encode public template + * and public template attr count in key_generate_pair(). + * kops->ko_key_object_id_ptr is used to encode public key + * in key_generate_pair(). + */ +typedef struct kcf_key_ops_params { + crypto_session_id_t ko_sid; + crypto_mech_type_t ko_framework_mechtype; + crypto_mechanism_t ko_mech; + crypto_object_attribute_t *ko_key_template; + uint_t ko_key_attribute_count; + crypto_object_id_t *ko_key_object_id_ptr; + crypto_object_attribute_t *ko_private_key_template; + uint_t ko_private_key_attribute_count; + crypto_object_id_t *ko_private_key_object_id_ptr; + crypto_key_t *ko_key; + uchar_t *ko_wrapped_key; + size_t *ko_wrapped_key_len_ptr; + crypto_object_attribute_t *ko_out_template1; + crypto_object_attribute_t *ko_out_template2; + uint_t ko_out_attribute_count1; + uint_t ko_out_attribute_count2; +} kcf_key_ops_params_t; + +/* + * po_pin and po_pin_len are used to encode new_pin and new_pin_len + * when wrapping set_pin() function parameters. + * + * po_pd is useful when the provider descriptor (pd) supplying the + * provider handle is different from the pd supplying the ops vector. + * This is true for the ext_info provider entry point where po_pd + * can be the pd of a logical provider. The pd supplying the ops vector + * is passed as an argument to kcf_submit_request(). + */ +typedef struct kcf_provmgmt_ops_params { + crypto_session_id_t po_sid; + char *po_pin; + size_t po_pin_len; + char *po_old_pin; + size_t po_old_pin_len; + char *po_label; + crypto_provider_ext_info_t *po_ext_info; + kcf_provider_desc_t *po_pd; +} kcf_provmgmt_ops_params_t; + +/* + * The operation type within a function group. + */ +typedef enum kcf_op_type { + /* common ops for all mechanisms */ + KCF_OP_INIT = 1, + KCF_OP_SINGLE, /* pkcs11 sense. So, INIT is already done */ + KCF_OP_UPDATE, + KCF_OP_FINAL, + KCF_OP_ATOMIC, + + /* digest_key op */ + KCF_OP_DIGEST_KEY, + + /* mac specific op */ + KCF_OP_MAC_VERIFY_ATOMIC, + + /* mac/cipher specific op */ + KCF_OP_MAC_VERIFY_DECRYPT_ATOMIC, + + /* sign_recover ops */ + KCF_OP_SIGN_RECOVER_INIT, + KCF_OP_SIGN_RECOVER, + KCF_OP_SIGN_RECOVER_ATOMIC, + + /* verify_recover ops */ + KCF_OP_VERIFY_RECOVER_INIT, + KCF_OP_VERIFY_RECOVER, + KCF_OP_VERIFY_RECOVER_ATOMIC, + + /* random number ops */ + KCF_OP_RANDOM_SEED, + KCF_OP_RANDOM_GENERATE, + + /* session management ops */ + KCF_OP_SESSION_OPEN, + KCF_OP_SESSION_CLOSE, + KCF_OP_SESSION_LOGIN, + KCF_OP_SESSION_LOGOUT, + + /* object management ops */ + KCF_OP_OBJECT_CREATE, + KCF_OP_OBJECT_COPY, + KCF_OP_OBJECT_DESTROY, + KCF_OP_OBJECT_GET_SIZE, + KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE, + KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE, + KCF_OP_OBJECT_FIND_INIT, + KCF_OP_OBJECT_FIND, + KCF_OP_OBJECT_FIND_FINAL, + + /* key management ops */ + KCF_OP_KEY_GENERATE, + KCF_OP_KEY_GENERATE_PAIR, + KCF_OP_KEY_WRAP, + KCF_OP_KEY_UNWRAP, + KCF_OP_KEY_DERIVE, + KCF_OP_KEY_CHECK, + + /* provider management ops */ + KCF_OP_MGMT_EXTINFO, + KCF_OP_MGMT_INITTOKEN, + KCF_OP_MGMT_INITPIN, + KCF_OP_MGMT_SETPIN +} kcf_op_type_t; + +/* + * The operation groups that need wrapping of parameters. This is somewhat + * similar to the function group type in spi.h except that this also includes + * all the functions that don't have a mechanism. + * + * The wrapper macros should never take these enum values as an argument. + * Rather, they are assigned in the macro itself since they are known + * from the macro name. + */ +typedef enum kcf_op_group { + KCF_OG_DIGEST = 1, + KCF_OG_MAC, + KCF_OG_ENCRYPT, + KCF_OG_DECRYPT, + KCF_OG_SIGN, + KCF_OG_VERIFY, + KCF_OG_ENCRYPT_MAC, + KCF_OG_MAC_DECRYPT, + KCF_OG_RANDOM, + KCF_OG_SESSION, + KCF_OG_OBJECT, + KCF_OG_KEY, + KCF_OG_PROVMGMT, + KCF_OG_NOSTORE_KEY +} kcf_op_group_t; + +/* + * The kcf_op_type_t enum values used here should be only for those + * operations for which there is a k-api routine in sys/crypto/api.h. + */ +#define IS_INIT_OP(ftype) ((ftype) == KCF_OP_INIT) +#define IS_SINGLE_OP(ftype) ((ftype) == KCF_OP_SINGLE) +#define IS_UPDATE_OP(ftype) ((ftype) == KCF_OP_UPDATE) +#define IS_FINAL_OP(ftype) ((ftype) == KCF_OP_FINAL) +#define IS_ATOMIC_OP(ftype) ( \ + (ftype) == KCF_OP_ATOMIC || (ftype) == KCF_OP_MAC_VERIFY_ATOMIC || \ + (ftype) == KCF_OP_MAC_VERIFY_DECRYPT_ATOMIC || \ + (ftype) == KCF_OP_SIGN_RECOVER_ATOMIC || \ + (ftype) == KCF_OP_VERIFY_RECOVER_ATOMIC) + +/* + * Keep the parameters associated with a request around. + * We need to pass them to the SPI. + */ +typedef struct kcf_req_params { + kcf_op_group_t rp_opgrp; + kcf_op_type_t rp_optype; + + union { + kcf_digest_ops_params_t digest_params; + kcf_mac_ops_params_t mac_params; + kcf_encrypt_ops_params_t encrypt_params; + kcf_decrypt_ops_params_t decrypt_params; + kcf_sign_ops_params_t sign_params; + kcf_verify_ops_params_t verify_params; + kcf_encrypt_mac_ops_params_t encrypt_mac_params; + kcf_mac_decrypt_ops_params_t mac_decrypt_params; + kcf_random_number_ops_params_t random_number_params; + kcf_session_ops_params_t session_params; + kcf_object_ops_params_t object_params; + kcf_key_ops_params_t key_params; + kcf_provmgmt_ops_params_t provmgmt_params; + } rp_u; +} kcf_req_params_t; + + +/* + * The ioctl/k-api code should bundle the parameters into a kcf_req_params_t + * structure before calling a scheduler routine. The following macros are + * available for that purpose. + * + * For the most part, the macro arguments closely correspond to the + * function parameters. In some cases, we use generic names. The comments + * for the structure should indicate these cases. + */ +#define KCF_WRAP_DIGEST_OPS_PARAMS(req, ftype, _sid, _mech, _key, \ + _data, _digest) { \ + kcf_digest_ops_params_t *dops = &(req)->rp_u.digest_params; \ + crypto_mechanism_t *mechp = _mech; \ + \ + (req)->rp_opgrp = KCF_OG_DIGEST; \ + (req)->rp_optype = ftype; \ + dops->do_sid = _sid; \ + if (mechp != NULL) { \ + dops->do_mech = *mechp; \ + dops->do_framework_mechtype = mechp->cm_type; \ + } \ + dops->do_digest_key = _key; \ + dops->do_data = _data; \ + dops->do_digest = _digest; \ +} + +#define KCF_WRAP_MAC_OPS_PARAMS(req, ftype, _sid, _mech, _key, \ + _data, _mac, _templ) { \ + kcf_mac_ops_params_t *mops = &(req)->rp_u.mac_params; \ + crypto_mechanism_t *mechp = _mech; \ + \ + (req)->rp_opgrp = KCF_OG_MAC; \ + (req)->rp_optype = ftype; \ + mops->mo_sid = _sid; \ + if (mechp != NULL) { \ + mops->mo_mech = *mechp; \ + mops->mo_framework_mechtype = mechp->cm_type; \ + } \ + mops->mo_key = _key; \ + mops->mo_data = _data; \ + mops->mo_mac = _mac; \ + mops->mo_templ = _templ; \ +} + +#define KCF_WRAP_ENCRYPT_OPS_PARAMS(req, ftype, _sid, _mech, _key, \ + _plaintext, _ciphertext, _templ) { \ + kcf_encrypt_ops_params_t *cops = &(req)->rp_u.encrypt_params; \ + crypto_mechanism_t *mechp = _mech; \ + \ + (req)->rp_opgrp = KCF_OG_ENCRYPT; \ + (req)->rp_optype = ftype; \ + cops->eo_sid = _sid; \ + if (mechp != NULL) { \ + cops->eo_mech = *mechp; \ + cops->eo_framework_mechtype = mechp->cm_type; \ + } \ + cops->eo_key = _key; \ + cops->eo_plaintext = _plaintext; \ + cops->eo_ciphertext = _ciphertext; \ + cops->eo_templ = _templ; \ +} + +#define KCF_WRAP_DECRYPT_OPS_PARAMS(req, ftype, _sid, _mech, _key, \ + _ciphertext, _plaintext, _templ) { \ + kcf_decrypt_ops_params_t *cops = &(req)->rp_u.decrypt_params; \ + crypto_mechanism_t *mechp = _mech; \ + \ + (req)->rp_opgrp = KCF_OG_DECRYPT; \ + (req)->rp_optype = ftype; \ + cops->dop_sid = _sid; \ + if (mechp != NULL) { \ + cops->dop_mech = *mechp; \ + cops->dop_framework_mechtype = mechp->cm_type; \ + } \ + cops->dop_key = _key; \ + cops->dop_ciphertext = _ciphertext; \ + cops->dop_plaintext = _plaintext; \ + cops->dop_templ = _templ; \ +} + +#define KCF_WRAP_SIGN_OPS_PARAMS(req, ftype, _sid, _mech, _key, \ + _data, _signature, _templ) { \ + kcf_sign_ops_params_t *sops = &(req)->rp_u.sign_params; \ + crypto_mechanism_t *mechp = _mech; \ + \ + (req)->rp_opgrp = KCF_OG_SIGN; \ + (req)->rp_optype = ftype; \ + sops->so_sid = _sid; \ + if (mechp != NULL) { \ + sops->so_mech = *mechp; \ + sops->so_framework_mechtype = mechp->cm_type; \ + } \ + sops->so_key = _key; \ + sops->so_data = _data; \ + sops->so_signature = _signature; \ + sops->so_templ = _templ; \ +} + +#define KCF_WRAP_VERIFY_OPS_PARAMS(req, ftype, _sid, _mech, _key, \ + _data, _signature, _templ) { \ + kcf_verify_ops_params_t *vops = &(req)->rp_u.verify_params; \ + crypto_mechanism_t *mechp = _mech; \ + \ + (req)->rp_opgrp = KCF_OG_VERIFY; \ + (req)->rp_optype = ftype; \ + vops->vo_sid = _sid; \ + if (mechp != NULL) { \ + vops->vo_mech = *mechp; \ + vops->vo_framework_mechtype = mechp->cm_type; \ + } \ + vops->vo_key = _key; \ + vops->vo_data = _data; \ + vops->vo_signature = _signature; \ + vops->vo_templ = _templ; \ +} + +#define KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(req, ftype, _sid, _encr_key, \ + _mac_key, _plaintext, _ciphertext, _mac, _encr_templ, _mac_templ) { \ + kcf_encrypt_mac_ops_params_t *cmops = &(req)->rp_u.encrypt_mac_params; \ + \ + (req)->rp_opgrp = KCF_OG_ENCRYPT_MAC; \ + (req)->rp_optype = ftype; \ + cmops->em_sid = _sid; \ + cmops->em_encr_key = _encr_key; \ + cmops->em_mac_key = _mac_key; \ + cmops->em_plaintext = _plaintext; \ + cmops->em_ciphertext = _ciphertext; \ + cmops->em_mac = _mac; \ + cmops->em_encr_templ = _encr_templ; \ + cmops->em_mac_templ = _mac_templ; \ +} + +#define KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(req, ftype, _sid, _mac_key, \ + _decr_key, _ciphertext, _mac, _plaintext, _mac_templ, _decr_templ) { \ + kcf_mac_decrypt_ops_params_t *cmops = &(req)->rp_u.mac_decrypt_params; \ + \ + (req)->rp_opgrp = KCF_OG_MAC_DECRYPT; \ + (req)->rp_optype = ftype; \ + cmops->md_sid = _sid; \ + cmops->md_mac_key = _mac_key; \ + cmops->md_decr_key = _decr_key; \ + cmops->md_ciphertext = _ciphertext; \ + cmops->md_mac = _mac; \ + cmops->md_plaintext = _plaintext; \ + cmops->md_mac_templ = _mac_templ; \ + cmops->md_decr_templ = _decr_templ; \ +} + +#define KCF_WRAP_RANDOM_OPS_PARAMS(req, ftype, _sid, _buf, _buflen, \ + _est, _flags) { \ + kcf_random_number_ops_params_t *rops = \ + &(req)->rp_u.random_number_params; \ + \ + (req)->rp_opgrp = KCF_OG_RANDOM; \ + (req)->rp_optype = ftype; \ + rops->rn_sid = _sid; \ + rops->rn_buf = _buf; \ + rops->rn_buflen = _buflen; \ + rops->rn_entropy_est = _est; \ + rops->rn_flags = _flags; \ +} + +#define KCF_WRAP_SESSION_OPS_PARAMS(req, ftype, _sid_ptr, _sid, \ + _user_type, _pin, _pin_len, _pd) { \ + kcf_session_ops_params_t *sops = &(req)->rp_u.session_params; \ + \ + (req)->rp_opgrp = KCF_OG_SESSION; \ + (req)->rp_optype = ftype; \ + sops->so_sid_ptr = _sid_ptr; \ + sops->so_sid = _sid; \ + sops->so_user_type = _user_type; \ + sops->so_pin = _pin; \ + sops->so_pin_len = _pin_len; \ + sops->so_pd = _pd; \ +} + +#define KCF_WRAP_OBJECT_OPS_PARAMS(req, ftype, _sid, _object_id, \ + _template, _attribute_count, _object_id_ptr, _object_size, \ + _find_init_pp_ptr, _find_pp, _max_object_count, _object_count_ptr) { \ + kcf_object_ops_params_t *jops = &(req)->rp_u.object_params; \ + \ + (req)->rp_opgrp = KCF_OG_OBJECT; \ + (req)->rp_optype = ftype; \ + jops->oo_sid = _sid; \ + jops->oo_object_id = _object_id; \ + jops->oo_template = _template; \ + jops->oo_attribute_count = _attribute_count; \ + jops->oo_object_id_ptr = _object_id_ptr; \ + jops->oo_object_size = _object_size; \ + jops->oo_find_init_pp_ptr = _find_init_pp_ptr; \ + jops->oo_find_pp = _find_pp; \ + jops->oo_max_object_count = _max_object_count; \ + jops->oo_object_count_ptr = _object_count_ptr; \ +} + +#define KCF_WRAP_KEY_OPS_PARAMS(req, ftype, _sid, _mech, _key_template, \ + _key_attribute_count, _key_object_id_ptr, _private_key_template, \ + _private_key_attribute_count, _private_key_object_id_ptr, \ + _key, _wrapped_key, _wrapped_key_len_ptr) { \ + kcf_key_ops_params_t *kops = &(req)->rp_u.key_params; \ + crypto_mechanism_t *mechp = _mech; \ + \ + (req)->rp_opgrp = KCF_OG_KEY; \ + (req)->rp_optype = ftype; \ + kops->ko_sid = _sid; \ + if (mechp != NULL) { \ + kops->ko_mech = *mechp; \ + kops->ko_framework_mechtype = mechp->cm_type; \ + } \ + kops->ko_key_template = _key_template; \ + kops->ko_key_attribute_count = _key_attribute_count; \ + kops->ko_key_object_id_ptr = _key_object_id_ptr; \ + kops->ko_private_key_template = _private_key_template; \ + kops->ko_private_key_attribute_count = _private_key_attribute_count; \ + kops->ko_private_key_object_id_ptr = _private_key_object_id_ptr; \ + kops->ko_key = _key; \ + kops->ko_wrapped_key = _wrapped_key; \ + kops->ko_wrapped_key_len_ptr = _wrapped_key_len_ptr; \ +} + +#define KCF_WRAP_PROVMGMT_OPS_PARAMS(req, ftype, _sid, _old_pin, \ + _old_pin_len, _pin, _pin_len, _label, _ext_info, _pd) { \ + kcf_provmgmt_ops_params_t *pops = &(req)->rp_u.provmgmt_params; \ + \ + (req)->rp_opgrp = KCF_OG_PROVMGMT; \ + (req)->rp_optype = ftype; \ + pops->po_sid = _sid; \ + pops->po_pin = _pin; \ + pops->po_pin_len = _pin_len; \ + pops->po_old_pin = _old_pin; \ + pops->po_old_pin_len = _old_pin_len; \ + pops->po_label = _label; \ + pops->po_ext_info = _ext_info; \ + pops->po_pd = _pd; \ +} + +#define KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(req, ftype, _sid, _mech, \ + _key_template, _key_attribute_count, _private_key_template, \ + _private_key_attribute_count, _key, _out_template1, \ + _out_attribute_count1, _out_template2, _out_attribute_count2) { \ + kcf_key_ops_params_t *kops = &(req)->rp_u.key_params; \ + crypto_mechanism_t *mechp = _mech; \ + \ + (req)->rp_opgrp = KCF_OG_NOSTORE_KEY; \ + (req)->rp_optype = ftype; \ + kops->ko_sid = _sid; \ + if (mechp != NULL) { \ + kops->ko_mech = *mechp; \ + kops->ko_framework_mechtype = mechp->cm_type; \ + } \ + kops->ko_key_template = _key_template; \ + kops->ko_key_attribute_count = _key_attribute_count; \ + kops->ko_key_object_id_ptr = NULL; \ + kops->ko_private_key_template = _private_key_template; \ + kops->ko_private_key_attribute_count = _private_key_attribute_count; \ + kops->ko_private_key_object_id_ptr = NULL; \ + kops->ko_key = _key; \ + kops->ko_wrapped_key = NULL; \ + kops->ko_wrapped_key_len_ptr = 0; \ + kops->ko_out_template1 = _out_template1; \ + kops->ko_out_template2 = _out_template2; \ + kops->ko_out_attribute_count1 = _out_attribute_count1; \ + kops->ko_out_attribute_count2 = _out_attribute_count2; \ +} + +#define KCF_SET_PROVIDER_MECHNUM(fmtype, pd, mechp) \ + (mechp)->cm_type = \ + KCF_TO_PROV_MECHNUM(pd, fmtype); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_CRYPTO_OPS_IMPL_H */ diff --git a/module/icp/include/sys/crypto/sched_impl.h b/module/icp/include/sys/crypto/sched_impl.h new file mode 100644 index 000000000..32ffa7749 --- /dev/null +++ b/module/icp/include/sys/crypto/sched_impl.h @@ -0,0 +1,531 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_CRYPTO_SCHED_IMPL_H +#define _SYS_CRYPTO_SCHED_IMPL_H + +/* + * Scheduler internal structures. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/zfs_context.h> +#include <sys/crypto/api.h> +#include <sys/crypto/spi.h> +#include <sys/crypto/impl.h> +#include <sys/crypto/common.h> +#include <sys/crypto/ops_impl.h> + +typedef void (kcf_func_t)(void *, int); + +typedef enum kcf_req_status { + REQ_ALLOCATED = 1, + REQ_WAITING, /* At the framework level */ + REQ_INPROGRESS, /* At the provider level */ + REQ_DONE, + REQ_CANCELED +} kcf_req_status_t; + +typedef enum kcf_call_type { + CRYPTO_SYNCH = 1, + CRYPTO_ASYNCH +} kcf_call_type_t; + +#define CHECK_RESTRICT(crq) (crq != NULL && \ + ((crq)->cr_flag & CRYPTO_RESTRICTED)) + +#define CHECK_RESTRICT_FALSE B_FALSE + +#define CHECK_FASTPATH(crq, pd) ((crq) == NULL || \ + !((crq)->cr_flag & CRYPTO_ALWAYS_QUEUE)) && \ + (pd)->pd_prov_type == CRYPTO_SW_PROVIDER + +#define KCF_KMFLAG(crq) (((crq) == NULL) ? KM_SLEEP : KM_NOSLEEP) + +/* + * The framework keeps an internal handle to use in the adaptive + * asynchronous case. This is the case when a client has the + * CRYPTO_ALWAYS_QUEUE bit clear and a software provider is used for + * the request. The request is completed in the context of the calling + * thread and kernel memory must be allocated with KM_NOSLEEP. + * + * The framework passes a pointer to the handle in crypto_req_handle_t + * argument when it calls the SPI of the software provider. The macros + * KCF_RHNDL() and KCF_SWFP_RHNDL() are used to do this. + * + * When a provider asks the framework for kmflag value via + * crypto_kmflag(9S) we use REQHNDL2_KMFLAG() macro. + */ +extern ulong_t kcf_swprov_hndl; +#define KCF_RHNDL(kmflag) (((kmflag) == KM_SLEEP) ? NULL : &kcf_swprov_hndl) +#define KCF_SWFP_RHNDL(crq) (((crq) == NULL) ? NULL : &kcf_swprov_hndl) +#define REQHNDL2_KMFLAG(rhndl) \ + ((rhndl == &kcf_swprov_hndl) ? KM_NOSLEEP : KM_SLEEP) + +/* Internal call_req flags. They start after the public ones in api.h */ + +#define CRYPTO_SETDUAL 0x00001000 /* Set the 'cont' boolean before */ + /* submitting the request */ +#define KCF_ISDUALREQ(crq) \ + (((crq) == NULL) ? B_FALSE : (crq->cr_flag & CRYPTO_SETDUAL)) + +typedef struct kcf_prov_tried { + kcf_provider_desc_t *pt_pd; + struct kcf_prov_tried *pt_next; +} kcf_prov_tried_t; + +#define IS_FG_SUPPORTED(mdesc, fg) \ + (((mdesc)->pm_mech_info.cm_func_group_mask & (fg)) != 0) + +#define IS_PROVIDER_TRIED(pd, tlist) \ + (tlist != NULL && is_in_triedlist(pd, tlist)) + +#define IS_RECOVERABLE(error) \ + (error == CRYPTO_BUFFER_TOO_BIG || \ + error == CRYPTO_BUSY || \ + error == CRYPTO_DEVICE_ERROR || \ + error == CRYPTO_DEVICE_MEMORY || \ + error == CRYPTO_KEY_SIZE_RANGE || \ + error == CRYPTO_NO_PERMISSION) + +#define KCF_ATOMIC_INCR(x) atomic_add_32(&(x), 1) +#define KCF_ATOMIC_DECR(x) atomic_add_32(&(x), -1) + +/* + * Node structure for synchronous requests. + */ +typedef struct kcf_sreq_node { + /* Should always be the first field in this structure */ + kcf_call_type_t sn_type; + /* + * sn_cv and sr_lock are used to wait for the + * operation to complete. sn_lock also protects + * the sn_state field. + */ + kcondvar_t sn_cv; + kmutex_t sn_lock; + kcf_req_status_t sn_state; + + /* + * Return value from the operation. This will be + * one of the CRYPTO_* errors defined in common.h. + */ + int sn_rv; + + /* + * parameters to call the SPI with. This can be + * a pointer as we know the caller context/stack stays. + */ + struct kcf_req_params *sn_params; + + /* Internal context for this request */ + struct kcf_context *sn_context; + + /* Provider handling this request */ + kcf_provider_desc_t *sn_provider; +} kcf_sreq_node_t; + +/* + * Node structure for asynchronous requests. A node can be on + * on a chain of requests hanging of the internal context + * structure and can be in the global software provider queue. + */ +typedef struct kcf_areq_node { + /* Should always be the first field in this structure */ + kcf_call_type_t an_type; + + /* an_lock protects the field an_state */ + kmutex_t an_lock; + kcf_req_status_t an_state; + crypto_call_req_t an_reqarg; + + /* + * parameters to call the SPI with. We need to + * save the params since the caller stack can go away. + */ + struct kcf_req_params an_params; + + /* + * The next two fields should be NULL for operations that + * don't need a context. + */ + /* Internal context for this request */ + struct kcf_context *an_context; + + /* next in chain of requests for context */ + struct kcf_areq_node *an_ctxchain_next; + + kcondvar_t an_turn_cv; + boolean_t an_is_my_turn; + boolean_t an_isdual; /* for internal reuse */ + + /* + * Next and previous nodes in the global software + * queue. These fields are NULL for a hardware + * provider since we use a taskq there. + */ + struct kcf_areq_node *an_next; + struct kcf_areq_node *an_prev; + + /* Provider handling this request */ + kcf_provider_desc_t *an_provider; + kcf_prov_tried_t *an_tried_plist; + + struct kcf_areq_node *an_idnext; /* Next in ID hash */ + struct kcf_areq_node *an_idprev; /* Prev in ID hash */ + kcondvar_t an_done; /* Signal request completion */ + uint_t an_refcnt; +} kcf_areq_node_t; + +#define KCF_AREQ_REFHOLD(areq) { \ + atomic_add_32(&(areq)->an_refcnt, 1); \ + ASSERT((areq)->an_refcnt != 0); \ +} + +#define KCF_AREQ_REFRELE(areq) { \ + ASSERT((areq)->an_refcnt != 0); \ + membar_exit(); \ + if (atomic_add_32_nv(&(areq)->an_refcnt, -1) == 0) \ + kcf_free_req(areq); \ +} + +#define GET_REQ_TYPE(arg) *((kcf_call_type_t *)(arg)) + +#define NOTIFY_CLIENT(areq, err) (*(areq)->an_reqarg.cr_callback_func)(\ + (areq)->an_reqarg.cr_callback_arg, err); + +/* For internally generated call requests for dual operations */ +typedef struct kcf_call_req { + crypto_call_req_t kr_callreq; /* external client call req */ + kcf_req_params_t kr_params; /* Params saved for next call */ + kcf_areq_node_t *kr_areq; /* Use this areq */ + off_t kr_saveoffset; + size_t kr_savelen; +} kcf_dual_req_t; + +/* + * The following are some what similar to macros in callo.h, which implement + * callout tables. + * + * The lower four bits of the ID are used to encode the table ID to + * index in to. The REQID_COUNTER_HIGH bit is used to avoid any check for + * wrap around when generating ID. We assume that there won't be a request + * which takes more time than 2^^(sizeof (long) - 5) other requests submitted + * after it. This ensures there won't be any ID collision. + */ +#define REQID_COUNTER_HIGH (1UL << (8 * sizeof (long) - 1)) +#define REQID_COUNTER_SHIFT 4 +#define REQID_COUNTER_LOW (1 << REQID_COUNTER_SHIFT) +#define REQID_TABLES 16 +#define REQID_TABLE_MASK (REQID_TABLES - 1) + +#define REQID_BUCKETS 512 +#define REQID_BUCKET_MASK (REQID_BUCKETS - 1) +#define REQID_HASH(id) (((id) >> REQID_COUNTER_SHIFT) & REQID_BUCKET_MASK) + +#define GET_REQID(areq) (areq)->an_reqarg.cr_reqid +#define SET_REQID(areq, val) GET_REQID(areq) = val + +/* + * Hash table for async requests. + */ +typedef struct kcf_reqid_table { + kmutex_t rt_lock; + crypto_req_id_t rt_curid; + kcf_areq_node_t *rt_idhash[REQID_BUCKETS]; +} kcf_reqid_table_t; + +/* + * Global software provider queue structure. Requests to be + * handled by a SW provider and have the ALWAYS_QUEUE flag set + * get queued here. + */ +typedef struct kcf_global_swq { + /* + * gs_cv and gs_lock are used to wait for new requests. + * gs_lock protects the changes to the queue. + */ + kcondvar_t gs_cv; + kmutex_t gs_lock; + uint_t gs_njobs; + uint_t gs_maxjobs; + kcf_areq_node_t *gs_first; + kcf_areq_node_t *gs_last; +} kcf_global_swq_t; + + +/* + * Internal representation of a canonical context. We contain crypto_ctx_t + * structure in order to have just one memory allocation. The SPI + * ((crypto_ctx_t *)ctx)->cc_framework_private maps to this structure. + */ +typedef struct kcf_context { + crypto_ctx_t kc_glbl_ctx; + uint_t kc_refcnt; + kmutex_t kc_in_use_lock; + /* + * kc_req_chain_first and kc_req_chain_last are used to chain + * multiple async requests using the same context. They should be + * NULL for sync requests. + */ + kcf_areq_node_t *kc_req_chain_first; + kcf_areq_node_t *kc_req_chain_last; + kcf_provider_desc_t *kc_prov_desc; /* Prov. descriptor */ + kcf_provider_desc_t *kc_sw_prov_desc; /* Prov. descriptor */ + kcf_mech_entry_t *kc_mech; + struct kcf_context *kc_secondctx; /* for dual contexts */ +} kcf_context_t; + +/* + * Bump up the reference count on the framework private context. A + * global context or a request that references this structure should + * do a hold. + */ +#define KCF_CONTEXT_REFHOLD(ictx) { \ + atomic_add_32(&(ictx)->kc_refcnt, 1); \ + ASSERT((ictx)->kc_refcnt != 0); \ +} + +/* + * Decrement the reference count on the framework private context. + * When the last reference is released, the framework private + * context structure is freed along with the global context. + */ +#define KCF_CONTEXT_REFRELE(ictx) { \ + ASSERT((ictx)->kc_refcnt != 0); \ + membar_exit(); \ + if (atomic_add_32_nv(&(ictx)->kc_refcnt, -1) == 0) \ + kcf_free_context(ictx); \ +} + +/* + * Check if we can release the context now. In case of CRYPTO_QUEUED + * we do not release it as we can do it only after the provider notified + * us. In case of CRYPTO_BUSY, the client can retry the request using + * the context, so we do not release the context. + * + * This macro should be called only from the final routine in + * an init/update/final sequence. We do not release the context in case + * of update operations. We require the consumer to free it + * explicitly, in case it wants to abandon the operation. This is done + * as there may be mechanisms in ECB mode that can continue even if + * an operation on a block fails. + */ +#define KCF_CONTEXT_COND_RELEASE(rv, kcf_ctx) { \ + if (KCF_CONTEXT_DONE(rv)) \ + KCF_CONTEXT_REFRELE(kcf_ctx); \ +} + +/* + * This macro determines whether we're done with a context. + */ +#define KCF_CONTEXT_DONE(rv) \ + ((rv) != CRYPTO_QUEUED && (rv) != CRYPTO_BUSY && \ + (rv) != CRYPTO_BUFFER_TOO_SMALL) + +/* + * A crypto_ctx_template_t is internally a pointer to this struct + */ +typedef struct kcf_ctx_template { + crypto_kcf_provider_handle_t ct_prov_handle; /* provider handle */ + uint_t ct_generation; /* generation # */ + size_t ct_size; /* for freeing */ + crypto_spi_ctx_template_t ct_prov_tmpl; /* context template */ + /* from the SW prov */ +} kcf_ctx_template_t; + +/* + * Structure for pool of threads working on global software queue. + */ +typedef struct kcf_pool { + uint32_t kp_threads; /* Number of threads in pool */ + uint32_t kp_idlethreads; /* Idle threads in pool */ + uint32_t kp_blockedthreads; /* Blocked threads in pool */ + + /* + * cv & lock to monitor the condition when no threads + * are around. In this case the failover thread kicks in. + */ + kcondvar_t kp_nothr_cv; + kmutex_t kp_thread_lock; + + /* Userspace thread creator variables. */ + boolean_t kp_signal_create_thread; /* Create requested flag */ + int kp_nthrs; /* # of threads to create */ + boolean_t kp_user_waiting; /* Thread waiting for work */ + + /* + * cv & lock for the condition where more threads need to be + * created. kp_user_lock also protects the three fileds above. + */ + kcondvar_t kp_user_cv; /* Creator cond. variable */ + kmutex_t kp_user_lock; /* Creator lock */ +} kcf_pool_t; + + +/* + * State of a crypto bufcall element. + */ +typedef enum cbuf_state { + CBUF_FREE = 1, + CBUF_WAITING, + CBUF_RUNNING +} cbuf_state_t; + +/* + * Structure of a crypto bufcall element. + */ +typedef struct kcf_cbuf_elem { + /* + * lock and cv to wait for CBUF_RUNNING to be done + * kc_lock also protects kc_state. + */ + kmutex_t kc_lock; + kcondvar_t kc_cv; + cbuf_state_t kc_state; + + struct kcf_cbuf_elem *kc_next; + struct kcf_cbuf_elem *kc_prev; + + void (*kc_func)(void *arg); + void *kc_arg; +} kcf_cbuf_elem_t; + +/* + * State of a notify element. + */ +typedef enum ntfy_elem_state { + NTFY_WAITING = 1, + NTFY_RUNNING +} ntfy_elem_state_t; + +/* + * Structure of a notify list element. + */ +typedef struct kcf_ntfy_elem { + /* + * lock and cv to wait for NTFY_RUNNING to be done. + * kn_lock also protects kn_state. + */ + kmutex_t kn_lock; + kcondvar_t kn_cv; + ntfy_elem_state_t kn_state; + + struct kcf_ntfy_elem *kn_next; + struct kcf_ntfy_elem *kn_prev; + + crypto_notify_callback_t kn_func; + uint32_t kn_event_mask; +} kcf_ntfy_elem_t; + + +/* + * The following values are based on the assumption that it would + * take around eight cpus to load a hardware provider (This is true for + * at least one product) and a kernel client may come from different + * low-priority interrupt levels. We will have CYRPTO_TASKQ_MIN number + * of cached taskq entries. The CRYPTO_TASKQ_MAX number is based on + * a throughput of 1GB/s using 512-byte buffers. These are just + * reasonable estimates and might need to change in future. + */ +#define CRYPTO_TASKQ_THREADS 8 +#define CYRPTO_TASKQ_MIN 64 +#define CRYPTO_TASKQ_MAX 2 * 1024 * 1024 + +extern int crypto_taskq_threads; +extern int crypto_taskq_minalloc; +extern int crypto_taskq_maxalloc; +extern kcf_global_swq_t *gswq; +extern int kcf_maxthreads; +extern int kcf_minthreads; + +/* + * All pending crypto bufcalls are put on a list. cbuf_list_lock + * protects changes to this list. + */ +extern kmutex_t cbuf_list_lock; +extern kcondvar_t cbuf_list_cv; + +/* + * All event subscribers are put on a list. kcf_notify_list_lock + * protects changes to this list. + */ +extern kmutex_t ntfy_list_lock; +extern kcondvar_t ntfy_list_cv; + +boolean_t kcf_get_next_logical_provider_member(kcf_provider_desc_t *, + kcf_provider_desc_t *, kcf_provider_desc_t **); +extern int kcf_get_hardware_provider(crypto_mech_type_t, crypto_mech_type_t, + boolean_t, kcf_provider_desc_t *, kcf_provider_desc_t **, + crypto_func_group_t); +extern int kcf_get_hardware_provider_nomech(offset_t, offset_t, + boolean_t, kcf_provider_desc_t *, kcf_provider_desc_t **); +extern void kcf_free_triedlist(kcf_prov_tried_t *); +extern kcf_prov_tried_t *kcf_insert_triedlist(kcf_prov_tried_t **, + kcf_provider_desc_t *, int); +extern kcf_provider_desc_t *kcf_get_mech_provider(crypto_mech_type_t, + kcf_mech_entry_t **, int *, kcf_prov_tried_t *, crypto_func_group_t, + boolean_t, size_t); +extern kcf_provider_desc_t *kcf_get_dual_provider(crypto_mechanism_t *, + crypto_mechanism_t *, kcf_mech_entry_t **, crypto_mech_type_t *, + crypto_mech_type_t *, int *, kcf_prov_tried_t *, + crypto_func_group_t, crypto_func_group_t, boolean_t, size_t); +extern crypto_ctx_t *kcf_new_ctx(crypto_call_req_t *, kcf_provider_desc_t *, + crypto_session_id_t); +extern int kcf_submit_request(kcf_provider_desc_t *, crypto_ctx_t *, + crypto_call_req_t *, kcf_req_params_t *, boolean_t); +extern void kcf_sched_destroy(void); +extern void kcf_sched_init(void); +extern void kcf_sched_start(void); +extern void kcf_sop_done(kcf_sreq_node_t *, int); +extern void kcf_aop_done(kcf_areq_node_t *, int); +extern int common_submit_request(kcf_provider_desc_t *, + crypto_ctx_t *, kcf_req_params_t *, crypto_req_handle_t); +extern void kcf_free_context(kcf_context_t *); + +extern int kcf_svc_wait(int *); +extern int kcf_svc_do_run(void); +extern int kcf_need_signature_verification(kcf_provider_desc_t *); +extern void kcf_verify_signature(void *); +extern struct modctl *kcf_get_modctl(crypto_provider_info_t *); +extern void verify_unverified_providers(void); +extern void kcf_free_req(kcf_areq_node_t *areq); +extern void crypto_bufcall_service(void); + +extern void kcf_walk_ntfylist(uint32_t, void *); +extern void kcf_do_notify(kcf_provider_desc_t *, boolean_t); + +extern kcf_dual_req_t *kcf_alloc_req(crypto_call_req_t *); +extern void kcf_next_req(void *, int); +extern void kcf_last_req(void *, int); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_CRYPTO_SCHED_IMPL_H */ diff --git a/module/icp/include/sys/crypto/spi.h b/module/icp/include/sys/crypto/spi.h new file mode 100644 index 000000000..b4d6467f9 --- /dev/null +++ b/module/icp/include/sys/crypto/spi.h @@ -0,0 +1,721 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_CRYPTO_SPI_H +#define _SYS_CRYPTO_SPI_H + +/* + * CSPI: Cryptographic Service Provider Interface. + */ + +#include <sys/zfs_context.h> +#include <sys/crypto/common.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +#define CRYPTO_SPI_VERSION_1 1 +#define CRYPTO_SPI_VERSION_2 2 +#define CRYPTO_SPI_VERSION_3 3 + +/* + * Provider-private handle. This handle is specified by a provider + * when it registers by means of the pi_provider_handle field of + * the crypto_provider_info structure, and passed to the provider + * when its entry points are invoked. + */ +typedef void *crypto_provider_handle_t; + +/* + * Context templates can be used to by software providers to pre-process + * keying material, such as key schedules. They are allocated by + * a software provider create_ctx_template(9E) entry point, and passed + * as argument to initialization and atomic provider entry points. + */ +typedef void *crypto_spi_ctx_template_t; + +/* + * Request handles are used by the kernel to identify an asynchronous + * request being processed by a provider. It is passed by the kernel + * to a hardware provider when submitting a request, and must be + * specified by a provider when calling crypto_op_notification(9F) + */ +typedef void *crypto_req_handle_t; + +/* Values for cc_flags field */ +#define CRYPTO_INIT_OPSTATE 0x00000001 /* allocate and init cc_opstate */ +#define CRYPTO_USE_OPSTATE 0x00000002 /* .. start using it as context */ + +/* + * The context structure is passed from the kernel to a provider. + * It contains the information needed to process a multi-part or + * single part operation. The context structure is not used + * by atomic operations. + * + * Parameters needed to perform a cryptographic operation, such + * as keys, mechanisms, input and output buffers, are passed + * as separate arguments to Provider routines. + */ +typedef struct crypto_ctx { + crypto_provider_handle_t cc_provider; + crypto_session_id_t cc_session; + void *cc_provider_private; /* owned by provider */ + void *cc_framework_private; /* owned by framework */ + uint32_t cc_flags; /* flags */ + void *cc_opstate; /* state */ +} crypto_ctx_t; + +/* + * Extended provider information. + */ + +/* + * valid values for ei_flags field of extended info structure + * They match the RSA Security, Inc PKCS#11 tokenInfo flags. + */ +#define CRYPTO_EXTF_RNG 0x00000001 +#define CRYPTO_EXTF_WRITE_PROTECTED 0x00000002 +#define CRYPTO_EXTF_LOGIN_REQUIRED 0x00000004 +#define CRYPTO_EXTF_USER_PIN_INITIALIZED 0x00000008 +#define CRYPTO_EXTF_CLOCK_ON_TOKEN 0x00000040 +#define CRYPTO_EXTF_PROTECTED_AUTHENTICATION_PATH 0x00000100 +#define CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS 0x00000200 +#define CRYPTO_EXTF_TOKEN_INITIALIZED 0x00000400 +#define CRYPTO_EXTF_USER_PIN_COUNT_LOW 0x00010000 +#define CRYPTO_EXTF_USER_PIN_FINAL_TRY 0x00020000 +#define CRYPTO_EXTF_USER_PIN_LOCKED 0x00040000 +#define CRYPTO_EXTF_USER_PIN_TO_BE_CHANGED 0x00080000 +#define CRYPTO_EXTF_SO_PIN_COUNT_LOW 0x00100000 +#define CRYPTO_EXTF_SO_PIN_FINAL_TRY 0x00200000 +#define CRYPTO_EXTF_SO_PIN_LOCKED 0x00400000 +#define CRYPTO_EXTF_SO_PIN_TO_BE_CHANGED 0x00800000 + +/* + * The crypto_control_ops structure contains pointers to control + * operations for cryptographic providers. It is passed through + * the crypto_ops(9S) structure when providers register with the + * kernel using crypto_register_provider(9F). + */ +typedef struct crypto_control_ops { + void (*provider_status)(crypto_provider_handle_t, uint_t *); +} crypto_control_ops_t; + +/* + * The crypto_ctx_ops structure contains points to context and context + * templates management operations for cryptographic providers. It is + * passed through the crypto_ops(9S) structure when providers register + * with the kernel using crypto_register_provider(9F). + */ +typedef struct crypto_ctx_ops { + int (*create_ctx_template)(crypto_provider_handle_t, + crypto_mechanism_t *, crypto_key_t *, + crypto_spi_ctx_template_t *, size_t *, crypto_req_handle_t); + int (*free_context)(crypto_ctx_t *); +} crypto_ctx_ops_t; + +/* + * The crypto_digest_ops structure contains pointers to digest + * operations for cryptographic providers. It is passed through + * the crypto_ops(9S) structure when providers register with the + * kernel using crypto_register_provider(9F). + */ +typedef struct crypto_digest_ops { + int (*digest_init)(crypto_ctx_t *, crypto_mechanism_t *, + crypto_req_handle_t); + int (*digest)(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, + crypto_req_handle_t); + int (*digest_update)(crypto_ctx_t *, crypto_data_t *, + crypto_req_handle_t); + int (*digest_key)(crypto_ctx_t *, crypto_key_t *, crypto_req_handle_t); + int (*digest_final)(crypto_ctx_t *, crypto_data_t *, + crypto_req_handle_t); + int (*digest_atomic)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_data_t *, + crypto_data_t *, crypto_req_handle_t); +} crypto_digest_ops_t; + +/* + * The crypto_cipher_ops structure contains pointers to encryption + * and decryption operations for cryptographic providers. It is + * passed through the crypto_ops(9S) structure when providers register + * with the kernel using crypto_register_provider(9F). + */ +typedef struct crypto_cipher_ops { + int (*encrypt_init)(crypto_ctx_t *, + crypto_mechanism_t *, crypto_key_t *, + crypto_spi_ctx_template_t, crypto_req_handle_t); + int (*encrypt)(crypto_ctx_t *, + crypto_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*encrypt_update)(crypto_ctx_t *, + crypto_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*encrypt_final)(crypto_ctx_t *, + crypto_data_t *, crypto_req_handle_t); + int (*encrypt_atomic)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, + crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); + + int (*decrypt_init)(crypto_ctx_t *, + crypto_mechanism_t *, crypto_key_t *, + crypto_spi_ctx_template_t, crypto_req_handle_t); + int (*decrypt)(crypto_ctx_t *, + crypto_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*decrypt_update)(crypto_ctx_t *, + crypto_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*decrypt_final)(crypto_ctx_t *, + crypto_data_t *, crypto_req_handle_t); + int (*decrypt_atomic)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, + crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); +} crypto_cipher_ops_t; + +/* + * The crypto_mac_ops structure contains pointers to MAC + * operations for cryptographic providers. It is passed through + * the crypto_ops(9S) structure when providers register with the + * kernel using crypto_register_provider(9F). + */ +typedef struct crypto_mac_ops { + int (*mac_init)(crypto_ctx_t *, + crypto_mechanism_t *, crypto_key_t *, + crypto_spi_ctx_template_t, crypto_req_handle_t); + int (*mac)(crypto_ctx_t *, + crypto_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*mac_update)(crypto_ctx_t *, + crypto_data_t *, crypto_req_handle_t); + int (*mac_final)(crypto_ctx_t *, + crypto_data_t *, crypto_req_handle_t); + int (*mac_atomic)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, + crypto_data_t *, crypto_spi_ctx_template_t, + crypto_req_handle_t); + int (*mac_verify_atomic)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, + crypto_data_t *, crypto_spi_ctx_template_t, + crypto_req_handle_t); +} crypto_mac_ops_t; + +/* + * The crypto_sign_ops structure contains pointers to signing + * operations for cryptographic providers. It is passed through + * the crypto_ops(9S) structure when providers register with the + * kernel using crypto_register_provider(9F). + */ +typedef struct crypto_sign_ops { + int (*sign_init)(crypto_ctx_t *, + crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t, + crypto_req_handle_t); + int (*sign)(crypto_ctx_t *, + crypto_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*sign_update)(crypto_ctx_t *, + crypto_data_t *, crypto_req_handle_t); + int (*sign_final)(crypto_ctx_t *, + crypto_data_t *, crypto_req_handle_t); + int (*sign_atomic)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, + crypto_data_t *, crypto_spi_ctx_template_t, + crypto_req_handle_t); + int (*sign_recover_init)(crypto_ctx_t *, crypto_mechanism_t *, + crypto_key_t *, crypto_spi_ctx_template_t, + crypto_req_handle_t); + int (*sign_recover)(crypto_ctx_t *, + crypto_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*sign_recover_atomic)(crypto_provider_handle_t, + crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, + crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t, + crypto_req_handle_t); +} crypto_sign_ops_t; + +/* + * The crypto_verify_ops structure contains pointers to verify + * operations for cryptographic providers. It is passed through + * the crypto_ops(9S) structure when providers register with the + * kernel using crypto_register_provider(9F). + */ +typedef struct crypto_verify_ops { + int (*verify_init)(crypto_ctx_t *, + crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t, + crypto_req_handle_t); + int (*do_verify)(crypto_ctx_t *, + crypto_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*verify_update)(crypto_ctx_t *, + crypto_data_t *, crypto_req_handle_t); + int (*verify_final)(crypto_ctx_t *, + crypto_data_t *, crypto_req_handle_t); + int (*verify_atomic)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, + crypto_data_t *, crypto_spi_ctx_template_t, + crypto_req_handle_t); + int (*verify_recover_init)(crypto_ctx_t *, crypto_mechanism_t *, + crypto_key_t *, crypto_spi_ctx_template_t, + crypto_req_handle_t); + int (*verify_recover)(crypto_ctx_t *, + crypto_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*verify_recover_atomic)(crypto_provider_handle_t, + crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, + crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t, + crypto_req_handle_t); +} crypto_verify_ops_t; + +/* + * The crypto_dual_ops structure contains pointers to dual + * cipher and sign/verify operations for cryptographic providers. + * It is passed through the crypto_ops(9S) structure when + * providers register with the kernel using + * crypto_register_provider(9F). + */ +typedef struct crypto_dual_ops { + int (*digest_encrypt_update)( + crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *, + crypto_data_t *, crypto_req_handle_t); + int (*decrypt_digest_update)( + crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *, + crypto_data_t *, crypto_req_handle_t); + int (*sign_encrypt_update)( + crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *, + crypto_data_t *, crypto_req_handle_t); + int (*decrypt_verify_update)( + crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *, + crypto_data_t *, crypto_req_handle_t); +} crypto_dual_ops_t; + +/* + * The crypto_dual_cipher_mac_ops structure contains pointers to dual + * cipher and MAC operations for cryptographic providers. + * It is passed through the crypto_ops(9S) structure when + * providers register with the kernel using + * crypto_register_provider(9F). + */ +typedef struct crypto_dual_cipher_mac_ops { + int (*encrypt_mac_init)(crypto_ctx_t *, + crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *, + crypto_key_t *, crypto_spi_ctx_template_t, + crypto_spi_ctx_template_t, crypto_req_handle_t); + int (*encrypt_mac)(crypto_ctx_t *, + crypto_data_t *, crypto_dual_data_t *, crypto_data_t *, + crypto_req_handle_t); + int (*encrypt_mac_update)(crypto_ctx_t *, + crypto_data_t *, crypto_dual_data_t *, crypto_req_handle_t); + int (*encrypt_mac_final)(crypto_ctx_t *, + crypto_dual_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*encrypt_mac_atomic)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *, + crypto_key_t *, crypto_data_t *, crypto_dual_data_t *, + crypto_data_t *, crypto_spi_ctx_template_t, + crypto_spi_ctx_template_t, crypto_req_handle_t); + + int (*mac_decrypt_init)(crypto_ctx_t *, + crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *, + crypto_key_t *, crypto_spi_ctx_template_t, + crypto_spi_ctx_template_t, crypto_req_handle_t); + int (*mac_decrypt)(crypto_ctx_t *, + crypto_dual_data_t *, crypto_data_t *, crypto_data_t *, + crypto_req_handle_t); + int (*mac_decrypt_update)(crypto_ctx_t *, + crypto_dual_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*mac_decrypt_final)(crypto_ctx_t *, + crypto_data_t *, crypto_data_t *, crypto_req_handle_t); + int (*mac_decrypt_atomic)(crypto_provider_handle_t, + crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, + crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *, + crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t, + crypto_spi_ctx_template_t, crypto_req_handle_t); + int (*mac_verify_decrypt_atomic)(crypto_provider_handle_t, + crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, + crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *, + crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t, + crypto_spi_ctx_template_t, crypto_req_handle_t); +} crypto_dual_cipher_mac_ops_t; + +/* + * The crypto_random_number_ops structure contains pointers to random + * number operations for cryptographic providers. It is passed through + * the crypto_ops(9S) structure when providers register with the + * kernel using crypto_register_provider(9F). + */ +typedef struct crypto_random_number_ops { + int (*seed_random)(crypto_provider_handle_t, crypto_session_id_t, + uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t); + int (*generate_random)(crypto_provider_handle_t, crypto_session_id_t, + uchar_t *, size_t, crypto_req_handle_t); +} crypto_random_number_ops_t; + +/* + * Flag values for seed_random. + */ +#define CRYPTO_SEED_NOW 0x00000001 + +/* + * The crypto_session_ops structure contains pointers to session + * operations for cryptographic providers. It is passed through + * the crypto_ops(9S) structure when providers register with the + * kernel using crypto_register_provider(9F). + */ +typedef struct crypto_session_ops { + int (*session_open)(crypto_provider_handle_t, crypto_session_id_t *, + crypto_req_handle_t); + int (*session_close)(crypto_provider_handle_t, crypto_session_id_t, + crypto_req_handle_t); + int (*session_login)(crypto_provider_handle_t, crypto_session_id_t, + crypto_user_type_t, char *, size_t, crypto_req_handle_t); + int (*session_logout)(crypto_provider_handle_t, crypto_session_id_t, + crypto_req_handle_t); +} crypto_session_ops_t; + +/* + * The crypto_object_ops structure contains pointers to object + * operations for cryptographic providers. It is passed through + * the crypto_ops(9S) structure when providers register with the + * kernel using crypto_register_provider(9F). + */ +typedef struct crypto_object_ops { + int (*object_create)(crypto_provider_handle_t, crypto_session_id_t, + crypto_object_attribute_t *, uint_t, crypto_object_id_t *, + crypto_req_handle_t); + int (*object_copy)(crypto_provider_handle_t, crypto_session_id_t, + crypto_object_id_t, crypto_object_attribute_t *, uint_t, + crypto_object_id_t *, crypto_req_handle_t); + int (*object_destroy)(crypto_provider_handle_t, crypto_session_id_t, + crypto_object_id_t, crypto_req_handle_t); + int (*object_get_size)(crypto_provider_handle_t, crypto_session_id_t, + crypto_object_id_t, size_t *, crypto_req_handle_t); + int (*object_get_attribute_value)(crypto_provider_handle_t, + crypto_session_id_t, crypto_object_id_t, + crypto_object_attribute_t *, uint_t, crypto_req_handle_t); + int (*object_set_attribute_value)(crypto_provider_handle_t, + crypto_session_id_t, crypto_object_id_t, + crypto_object_attribute_t *, uint_t, crypto_req_handle_t); + int (*object_find_init)(crypto_provider_handle_t, crypto_session_id_t, + crypto_object_attribute_t *, uint_t, void **, + crypto_req_handle_t); + int (*object_find)(crypto_provider_handle_t, void *, + crypto_object_id_t *, uint_t, uint_t *, crypto_req_handle_t); + int (*object_find_final)(crypto_provider_handle_t, void *, + crypto_req_handle_t); +} crypto_object_ops_t; + +/* + * The crypto_key_ops structure contains pointers to key + * operations for cryptographic providers. It is passed through + * the crypto_ops(9S) structure when providers register with the + * kernel using crypto_register_provider(9F). + */ +typedef struct crypto_key_ops { + int (*key_generate)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_object_attribute_t *, uint_t, + crypto_object_id_t *, crypto_req_handle_t); + int (*key_generate_pair)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_object_attribute_t *, uint_t, + crypto_object_attribute_t *, uint_t, crypto_object_id_t *, + crypto_object_id_t *, crypto_req_handle_t); + int (*key_wrap)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_object_id_t *, + uchar_t *, size_t *, crypto_req_handle_t); + int (*key_unwrap)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, uchar_t *, size_t *, + crypto_object_attribute_t *, uint_t, + crypto_object_id_t *, crypto_req_handle_t); + int (*key_derive)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_object_attribute_t *, + uint_t, crypto_object_id_t *, crypto_req_handle_t); + int (*key_check)(crypto_provider_handle_t, crypto_mechanism_t *, + crypto_key_t *); +} crypto_key_ops_t; + +/* + * The crypto_provider_management_ops structure contains pointers + * to management operations for cryptographic providers. It is passed + * through the crypto_ops(9S) structure when providers register with the + * kernel using crypto_register_provider(9F). + */ +typedef struct crypto_provider_management_ops { + int (*ext_info)(crypto_provider_handle_t, + crypto_provider_ext_info_t *, crypto_req_handle_t); + int (*init_token)(crypto_provider_handle_t, char *, size_t, + char *, crypto_req_handle_t); + int (*init_pin)(crypto_provider_handle_t, crypto_session_id_t, + char *, size_t, crypto_req_handle_t); + int (*set_pin)(crypto_provider_handle_t, crypto_session_id_t, + char *, size_t, char *, size_t, crypto_req_handle_t); +} crypto_provider_management_ops_t; + +typedef struct crypto_mech_ops { + int (*copyin_mechanism)(crypto_provider_handle_t, + crypto_mechanism_t *, crypto_mechanism_t *, int *, int); + int (*copyout_mechanism)(crypto_provider_handle_t, + crypto_mechanism_t *, crypto_mechanism_t *, int *, int); + int (*free_mechanism)(crypto_provider_handle_t, crypto_mechanism_t *); +} crypto_mech_ops_t; + +typedef struct crypto_nostore_key_ops { + int (*nostore_key_generate)(crypto_provider_handle_t, + crypto_session_id_t, crypto_mechanism_t *, + crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *, + uint_t, crypto_req_handle_t); + int (*nostore_key_generate_pair)(crypto_provider_handle_t, + crypto_session_id_t, crypto_mechanism_t *, + crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *, + uint_t, crypto_object_attribute_t *, uint_t, + crypto_object_attribute_t *, uint_t, crypto_req_handle_t); + int (*nostore_key_derive)(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_object_attribute_t *, + uint_t, crypto_object_attribute_t *, uint_t, crypto_req_handle_t); +} crypto_nostore_key_ops_t; + +/* + * The crypto_ops(9S) structure contains the structures containing + * the pointers to functions implemented by cryptographic providers. + * It is specified as part of the crypto_provider_info(9S) + * supplied by a provider when it registers with the kernel + * by calling crypto_register_provider(9F). + */ +typedef struct crypto_ops_v1 { + crypto_control_ops_t *co_control_ops; + crypto_digest_ops_t *co_digest_ops; + crypto_cipher_ops_t *co_cipher_ops; + crypto_mac_ops_t *co_mac_ops; + crypto_sign_ops_t *co_sign_ops; + crypto_verify_ops_t *co_verify_ops; + crypto_dual_ops_t *co_dual_ops; + crypto_dual_cipher_mac_ops_t *co_dual_cipher_mac_ops; + crypto_random_number_ops_t *co_random_ops; + crypto_session_ops_t *co_session_ops; + crypto_object_ops_t *co_object_ops; + crypto_key_ops_t *co_key_ops; + crypto_provider_management_ops_t *co_provider_ops; + crypto_ctx_ops_t *co_ctx_ops; +} crypto_ops_v1_t; + +typedef struct crypto_ops_v2 { + crypto_ops_v1_t v1_ops; + crypto_mech_ops_t *co_mech_ops; +} crypto_ops_v2_t; + +typedef struct crypto_ops_v3 { + crypto_ops_v2_t v2_ops; + crypto_nostore_key_ops_t *co_nostore_key_ops; +} crypto_ops_v3_t; + +typedef struct crypto_ops { + union { + crypto_ops_v3_t cou_v3; + crypto_ops_v2_t cou_v2; + crypto_ops_v1_t cou_v1; + } cou; +} crypto_ops_t; + +#define co_control_ops cou.cou_v1.co_control_ops +#define co_digest_ops cou.cou_v1.co_digest_ops +#define co_cipher_ops cou.cou_v1.co_cipher_ops +#define co_mac_ops cou.cou_v1.co_mac_ops +#define co_sign_ops cou.cou_v1.co_sign_ops +#define co_verify_ops cou.cou_v1.co_verify_ops +#define co_dual_ops cou.cou_v1.co_dual_ops +#define co_dual_cipher_mac_ops cou.cou_v1.co_dual_cipher_mac_ops +#define co_random_ops cou.cou_v1.co_random_ops +#define co_session_ops cou.cou_v1.co_session_ops +#define co_object_ops cou.cou_v1.co_object_ops +#define co_key_ops cou.cou_v1.co_key_ops +#define co_provider_ops cou.cou_v1.co_provider_ops +#define co_ctx_ops cou.cou_v1.co_ctx_ops +#define co_mech_ops cou.cou_v2.co_mech_ops +#define co_nostore_key_ops cou.cou_v3.co_nostore_key_ops + +/* + * The mechanism info structure crypto_mech_info_t contains a function group + * bit mask cm_func_group_mask. This field, of type crypto_func_group_t, + * specifies the provider entry point that can be used a particular + * mechanism. The function group mask is a combination of the following values. + */ + +typedef uint32_t crypto_func_group_t; + + +#define CRYPTO_FG_ENCRYPT 0x00000001 /* encrypt_init() */ +#define CRYPTO_FG_DECRYPT 0x00000002 /* decrypt_init() */ +#define CRYPTO_FG_DIGEST 0x00000004 /* digest_init() */ +#define CRYPTO_FG_SIGN 0x00000008 /* sign_init() */ +#define CRYPTO_FG_SIGN_RECOVER 0x00000010 /* sign_recover_init() */ +#define CRYPTO_FG_VERIFY 0x00000020 /* verify_init() */ +#define CRYPTO_FG_VERIFY_RECOVER 0x00000040 /* verify_recover_init() */ +#define CRYPTO_FG_GENERATE 0x00000080 /* key_generate() */ +#define CRYPTO_FG_GENERATE_KEY_PAIR 0x00000100 /* key_generate_pair() */ +#define CRYPTO_FG_WRAP 0x00000200 /* key_wrap() */ +#define CRYPTO_FG_UNWRAP 0x00000400 /* key_unwrap() */ +#define CRYPTO_FG_DERIVE 0x00000800 /* key_derive() */ +#define CRYPTO_FG_MAC 0x00001000 /* mac_init() */ +#define CRYPTO_FG_ENCRYPT_MAC 0x00002000 /* encrypt_mac_init() */ +#define CRYPTO_FG_MAC_DECRYPT 0x00004000 /* decrypt_mac_init() */ +#define CRYPTO_FG_ENCRYPT_ATOMIC 0x00008000 /* encrypt_atomic() */ +#define CRYPTO_FG_DECRYPT_ATOMIC 0x00010000 /* decrypt_atomic() */ +#define CRYPTO_FG_MAC_ATOMIC 0x00020000 /* mac_atomic() */ +#define CRYPTO_FG_DIGEST_ATOMIC 0x00040000 /* digest_atomic() */ +#define CRYPTO_FG_SIGN_ATOMIC 0x00080000 /* sign_atomic() */ +#define CRYPTO_FG_SIGN_RECOVER_ATOMIC 0x00100000 /* sign_recover_atomic() */ +#define CRYPTO_FG_VERIFY_ATOMIC 0x00200000 /* verify_atomic() */ +#define CRYPTO_FG_VERIFY_RECOVER_ATOMIC 0x00400000 /* verify_recover_atomic() */ +#define CRYPTO_FG_ENCRYPT_MAC_ATOMIC 0x00800000 /* encrypt_mac_atomic() */ +#define CRYPTO_FG_MAC_DECRYPT_ATOMIC 0x01000000 /* mac_decrypt_atomic() */ +#define CRYPTO_FG_RESERVED 0x80000000 + +/* + * Maximum length of the pi_provider_description field of the + * crypto_provider_info structure. + */ +#define CRYPTO_PROVIDER_DESCR_MAX_LEN 64 + + +/* Bit mask for all the simple operations */ +#define CRYPTO_FG_SIMPLEOP_MASK (CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | \ + CRYPTO_FG_DIGEST | CRYPTO_FG_SIGN | CRYPTO_FG_VERIFY | CRYPTO_FG_MAC | \ + CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_DECRYPT_ATOMIC | \ + CRYPTO_FG_MAC_ATOMIC | CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_SIGN_ATOMIC | \ + CRYPTO_FG_VERIFY_ATOMIC) + +/* Bit mask for all the dual operations */ +#define CRYPTO_FG_MAC_CIPHER_MASK (CRYPTO_FG_ENCRYPT_MAC | \ + CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_MAC_ATOMIC | \ + CRYPTO_FG_MAC_DECRYPT_ATOMIC) + +/* Add other combos to CRYPTO_FG_DUAL_MASK */ +#define CRYPTO_FG_DUAL_MASK CRYPTO_FG_MAC_CIPHER_MASK + +/* + * The crypto_mech_info structure specifies one of the mechanisms + * supported by a cryptographic provider. The pi_mechanisms field of + * the crypto_provider_info structure contains a pointer to an array + * of crypto_mech_info's. + */ +typedef struct crypto_mech_info { + crypto_mech_name_t cm_mech_name; + crypto_mech_type_t cm_mech_number; + crypto_func_group_t cm_func_group_mask; + ssize_t cm_min_key_length; + ssize_t cm_max_key_length; + uint32_t cm_mech_flags; +} crypto_mech_info_t; + +/* Alias the old name to the new name for compatibility. */ +#define cm_keysize_unit cm_mech_flags + +/* + * The following is used by a provider that sets + * CRYPTO_HASH_NO_UPDATE. It needs to specify the maximum + * input data size it can digest in this field. + */ +#define cm_max_input_length cm_max_key_length + +/* + * crypto_kcf_provider_handle_t is a handle allocated by the kernel. + * It is returned after the provider registers with + * crypto_register_provider(), and must be specified by the provider + * when calling crypto_unregister_provider(), and + * crypto_provider_notification(). + */ +typedef uint_t crypto_kcf_provider_handle_t; + +/* + * Provider information. Passed as argument to crypto_register_provider(9F). + * Describes the provider and its capabilities. Multiple providers can + * register for the same device instance. In this case, the same + * pi_provider_dev must be specified with a different pi_provider_handle. + */ +typedef struct crypto_provider_info_v1 { + uint_t pi_interface_version; + char *pi_provider_description; + crypto_provider_type_t pi_provider_type; + crypto_provider_handle_t pi_provider_handle; + crypto_ops_t *pi_ops_vector; + uint_t pi_mech_list_count; + crypto_mech_info_t *pi_mechanisms; + uint_t pi_logical_provider_count; + crypto_kcf_provider_handle_t *pi_logical_providers; +} crypto_provider_info_v1_t; + +typedef struct crypto_provider_info_v2 { + crypto_provider_info_v1_t v1_info; + uint_t pi_flags; +} crypto_provider_info_v2_t; + +typedef struct crypto_provider_info { + union { + crypto_provider_info_v2_t piu_v2; + crypto_provider_info_v1_t piu_v1; + } piu; +} crypto_provider_info_t; + +#define pi_interface_version piu.piu_v1.pi_interface_version +#define pi_provider_description piu.piu_v1.pi_provider_description +#define pi_provider_type piu.piu_v1.pi_provider_type +#define pi_provider_handle piu.piu_v1.pi_provider_handle +#define pi_ops_vector piu.piu_v1.pi_ops_vector +#define pi_mech_list_count piu.piu_v1.pi_mech_list_count +#define pi_mechanisms piu.piu_v1.pi_mechanisms +#define pi_logical_provider_count piu.piu_v1.pi_logical_provider_count +#define pi_logical_providers piu.piu_v1.pi_logical_providers +#define pi_flags piu.piu_v2.pi_flags + +/* hidden providers can only be accessed via a logical provider */ +#define CRYPTO_HIDE_PROVIDER 0x00000001 +/* + * provider can not do multi-part digest (updates) and has a limit + * on maximum input data that it can digest. + */ +#define CRYPTO_HASH_NO_UPDATE 0x00000002 + +/* provider can handle the request without returning a CRYPTO_QUEUED */ +#define CRYPTO_SYNCHRONOUS 0x00000004 + +#define CRYPTO_PIFLAGS_RESERVED2 0x40000000 +#define CRYPTO_PIFLAGS_RESERVED1 0x80000000 + +/* + * Provider status passed by a provider to crypto_provider_notification(9F) + * and returned by the provider_stauts(9E) entry point. + */ +#define CRYPTO_PROVIDER_READY 0 +#define CRYPTO_PROVIDER_BUSY 1 +#define CRYPTO_PROVIDER_FAILED 2 + +/* + * Functions exported by Solaris to cryptographic providers. Providers + * call these functions to register and unregister, notify the kernel + * of state changes, and notify the kernel when a asynchronous request + * completed. + */ +extern int crypto_register_provider(crypto_provider_info_t *, + crypto_kcf_provider_handle_t *); +extern int crypto_unregister_provider(crypto_kcf_provider_handle_t); +extern void crypto_provider_notification(crypto_kcf_provider_handle_t, uint_t); +extern void crypto_op_notification(crypto_req_handle_t, int); +extern int crypto_kmflag(crypto_req_handle_t); + + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_CRYPTO_SPI_H */ diff --git a/module/icp/include/sys/ia32/asm_linkage.h b/module/icp/include/sys/ia32/asm_linkage.h new file mode 100644 index 000000000..f2dae7093 --- /dev/null +++ b/module/icp/include/sys/ia32/asm_linkage.h @@ -0,0 +1,307 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _IA32_SYS_ASM_LINKAGE_H +#define _IA32_SYS_ASM_LINKAGE_H + +#include <sys/stack.h> +#include <sys/trap.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _ASM /* The remainder of this file is only for assembly files */ + +/* + * make annoying differences in assembler syntax go away + */ + +/* + * D16 and A16 are used to insert instructions prefixes; the + * macros help the assembler code be slightly more portable. + */ +#if !defined(__GNUC_AS__) +/* + * /usr/ccs/bin/as prefixes are parsed as separate instructions + */ +#define D16 data16; +#define A16 addr16; + +/* + * (There are some weird constructs in constant expressions) + */ +#define _CONST(const) [const] +#define _BITNOT(const) -1!_CONST(const) +#define _MUL(a, b) _CONST(a \* b) + +#else +/* + * Why not use the 'data16' and 'addr16' prefixes .. well, the + * assembler doesn't quite believe in real mode, and thus argues with + * us about what we're trying to do. + */ +#define D16 .byte 0x66; +#define A16 .byte 0x67; + +#define _CONST(const) (const) +#define _BITNOT(const) ~_CONST(const) +#define _MUL(a, b) _CONST(a * b) + +#endif + +/* + * C pointers are different sizes between i386 and amd64. + * These constants can be used to compute offsets into pointer arrays. + */ +#if defined(__amd64) +#define CLONGSHIFT 3 +#define CLONGSIZE 8 +#define CLONGMASK 7 +#elif defined(__i386) +#define CLONGSHIFT 2 +#define CLONGSIZE 4 +#define CLONGMASK 3 +#endif + +/* + * Since we know we're either ILP32 or LP64 .. + */ +#define CPTRSHIFT CLONGSHIFT +#define CPTRSIZE CLONGSIZE +#define CPTRMASK CLONGMASK + +#if CPTRSIZE != (1 << CPTRSHIFT) || CLONGSIZE != (1 << CLONGSHIFT) +#error "inconsistent shift constants" +#endif + +#if CPTRMASK != (CPTRSIZE - 1) || CLONGMASK != (CLONGSIZE - 1) +#error "inconsistent mask constants" +#endif + +#define ASM_ENTRY_ALIGN 16 + +/* + * SSE register alignment and save areas + */ + +#define XMM_SIZE 16 +#define XMM_ALIGN 16 + +#if defined(__amd64) + +#define SAVE_XMM_PROLOG(sreg, nreg) \ + subq $_CONST(_MUL(XMM_SIZE, nreg)), %rsp; \ + movq %rsp, sreg + +#define RSTOR_XMM_EPILOG(sreg, nreg) \ + addq $_CONST(_MUL(XMM_SIZE, nreg)), %rsp + +#elif defined(__i386) + +#define SAVE_XMM_PROLOG(sreg, nreg) \ + subl $_CONST(_MUL(XMM_SIZE, nreg) + XMM_ALIGN), %esp; \ + movl %esp, sreg; \ + addl $XMM_ALIGN, sreg; \ + andl $_BITNOT(XMM_ALIGN-1), sreg + +#define RSTOR_XMM_EPILOG(sreg, nreg) \ + addl $_CONST(_MUL(XMM_SIZE, nreg) + XMM_ALIGN), %esp; + +#endif /* __i386 */ + +/* + * profiling causes definitions of the MCOUNT and RTMCOUNT + * particular to the type + */ +#ifdef GPROF + +#define MCOUNT(x) \ + pushl %ebp; \ + movl %esp, %ebp; \ + call _mcount; \ + popl %ebp + +#endif /* GPROF */ + +#ifdef PROF + +#define MCOUNT(x) \ +/* CSTYLED */ \ + .lcomm .L_/**/x/**/1, 4, 4; \ + pushl %ebp; \ + movl %esp, %ebp; \ +/* CSTYLED */ \ + movl $.L_/**/x/**/1, %edx; \ + call _mcount; \ + popl %ebp + +#endif /* PROF */ + +/* + * if we are not profiling, MCOUNT should be defined to nothing + */ +#if !defined(PROF) && !defined(GPROF) +#define MCOUNT(x) +#endif /* !defined(PROF) && !defined(GPROF) */ + +#define RTMCOUNT(x) MCOUNT(x) + +/* + * Macro to define weak symbol aliases. These are similar to the ANSI-C + * #pragma weak _name = name + * except a compiler can determine type. The assembler must be told. Hence, + * the second parameter must be the type of the symbol (i.e.: function,...) + */ +#define ANSI_PRAGMA_WEAK(sym, stype) \ +/* CSTYLED */ \ + .weak _/**/sym; \ +/* CSTYLED */ \ + .type _/**/sym, @stype; \ +/* CSTYLED */ \ +_/**/sym = sym + +/* + * Like ANSI_PRAGMA_WEAK(), but for unrelated names, as in: + * #pragma weak sym1 = sym2 + */ +#define ANSI_PRAGMA_WEAK2(sym1, sym2, stype) \ + .weak sym1; \ + .type sym1, @stype; \ +sym1 = sym2 + +/* + * ENTRY provides the standard procedure entry code and an easy way to + * insert the calls to mcount for profiling. ENTRY_NP is identical, but + * never calls mcount. + */ +#define ENTRY(x) \ + .text; \ + .align ASM_ENTRY_ALIGN; \ + .globl x; \ + .type x, @function; \ +x: MCOUNT(x) + +#define ENTRY_NP(x) \ + .text; \ + .align ASM_ENTRY_ALIGN; \ + .globl x; \ + .type x, @function; \ +x: + +#define RTENTRY(x) \ + .text; \ + .align ASM_ENTRY_ALIGN; \ + .globl x; \ + .type x, @function; \ +x: RTMCOUNT(x) + +/* + * ENTRY2 is identical to ENTRY but provides two labels for the entry point. + */ +#define ENTRY2(x, y) \ + .text; \ + .align ASM_ENTRY_ALIGN; \ + .globl x, y; \ + .type x, @function; \ + .type y, @function; \ +/* CSTYLED */ \ +x: ; \ +y: MCOUNT(x) + +#define ENTRY_NP2(x, y) \ + .text; \ + .align ASM_ENTRY_ALIGN; \ + .globl x, y; \ + .type x, @function; \ + .type y, @function; \ +/* CSTYLED */ \ +x: ; \ +y: + + +/* + * ALTENTRY provides for additional entry points. + */ +#define ALTENTRY(x) \ + .globl x; \ + .type x, @function; \ +x: + +/* + * DGDEF and DGDEF2 provide global data declarations. + * + * DGDEF provides a word aligned word of storage. + * + * DGDEF2 allocates "sz" bytes of storage with **NO** alignment. This + * implies this macro is best used for byte arrays. + * + * DGDEF3 allocates "sz" bytes of storage with "algn" alignment. + */ +#define DGDEF2(name, sz) \ + .data; \ + .globl name; \ + .type name, @object; \ + .size name, sz; \ +name: + +#define DGDEF3(name, sz, algn) \ + .data; \ + .align algn; \ + .globl name; \ + .type name, @object; \ + .size name, sz; \ +name: + +#define DGDEF(name) DGDEF3(name, 4, 4) + +/* + * SET_SIZE trails a function and set the size for the ELF symbol table. + */ +#define SET_SIZE(x) \ + .size x, [.-x] + +/* + * NWORD provides native word value. + */ +#if defined(__amd64) + +/*CSTYLED*/ +#define NWORD quad + +#elif defined(__i386) + +#define NWORD long + +#endif /* __i386 */ + +#endif /* _ASM */ + +#ifdef __cplusplus +} +#endif + +#endif /* _IA32_SYS_ASM_LINKAGE_H */ diff --git a/module/icp/include/sys/ia32/stack.h b/module/icp/include/sys/ia32/stack.h new file mode 100644 index 000000000..c4deb7bca --- /dev/null +++ b/module/icp/include/sys/ia32/stack.h @@ -0,0 +1,160 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _IA32_SYS_STACK_H +#define _IA32_SYS_STACK_H + +#if !defined(_ASM) + +#include <sys/types.h> + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * In the x86 world, a stack frame looks like this: + * + * |--------------------------| + * 4n+8(%ebp) ->| argument word n | + * | ... | (Previous frame) + * 8(%ebp) ->| argument word 0 | + * |--------------------------|-------------------- + * 4(%ebp) ->| return address | + * |--------------------------| + * 0(%ebp) ->| previous %ebp (optional) | + * |--------------------------| + * -4(%ebp) ->| unspecified | (Current frame) + * | ... | + * 0(%esp) ->| variable size | + * |--------------------------| + */ + +/* + * Stack alignment macros. + */ + +#define STACK_ALIGN32 4 +#define STACK_ENTRY_ALIGN32 4 +#define STACK_BIAS32 0 +#define SA32(x) (((x)+(STACK_ALIGN32-1)) & ~(STACK_ALIGN32-1)) +#define STACK_RESERVE32 0 +#define MINFRAME32 0 + +#if defined(__amd64) + +/* + * In the amd64 world, a stack frame looks like this: + * + * |--------------------------| + * 8n+16(%rbp)->| argument word n | + * | ... | (Previous frame) + * 16(%rbp) ->| argument word 0 | + * |--------------------------|-------------------- + * 8(%rbp) ->| return address | + * |--------------------------| + * 0(%rbp) ->| previous %rbp | + * |--------------------------| + * -8(%rbp) ->| unspecified | (Current frame) + * | ... | + * 0(%rsp) ->| variable size | + * |--------------------------| + * -128(%rsp) ->| reserved for function | + * |--------------------------| + * + * The end of the input argument area must be aligned on a 16-byte + * boundary; i.e. (%rsp - 8) % 16 == 0 at function entry. + * + * The 128-byte location beyond %rsp is considered to be reserved for + * functions and is NOT modified by signal handlers. It can be used + * to store temporary data that is not needed across function calls. + */ + +/* + * Stack alignment macros. + */ + +#define STACK_ALIGN64 16 +#define STACK_ENTRY_ALIGN64 8 +#define STACK_BIAS64 0 +#define SA64(x) (((x)+(STACK_ALIGN64-1)) & ~(STACK_ALIGN64-1)) +#define STACK_RESERVE64 128 +#define MINFRAME64 0 + +#define STACK_ALIGN STACK_ALIGN64 +#define STACK_ENTRY_ALIGN STACK_ENTRY_ALIGN64 +#define STACK_BIAS STACK_BIAS64 +#define SA(x) SA64(x) +#define STACK_RESERVE STACK_RESERVE64 +#define MINFRAME MINFRAME64 + +#elif defined(__i386) + +#define STACK_ALIGN STACK_ALIGN32 +#define STACK_ENTRY_ALIGN STACK_ENTRY_ALIGN32 +#define STACK_BIAS STACK_BIAS32 +#define SA(x) SA32(x) +#define STACK_RESERVE STACK_RESERVE32 +#define MINFRAME MINFRAME32 + +#endif /* __i386 */ + +#if defined(_KERNEL) && !defined(_ASM) + +#if defined(DEBUG) +#if STACK_ALIGN == 4 +#define ASSERT_STACK_ALIGNED() \ + { \ + uint32_t __tmp; \ + ASSERT((((uintptr_t)&__tmp) & (STACK_ALIGN - 1)) == 0); \ + } +#elif (STACK_ALIGN == 16) && (_LONG_DOUBLE_ALIGNMENT == 16) +#define ASSERT_STACK_ALIGNED() \ + { \ + long double __tmp; \ + ASSERT((((uintptr_t)&__tmp) & (STACK_ALIGN - 1)) == 0); \ + } +#endif +#else /* DEBUG */ +#define ASSERT_STACK_ALIGNED() +#endif /* DEBUG */ + +struct regs; + +void traceregs(struct regs *); +void traceback(caddr_t); + +#endif /* defined(_KERNEL) && !defined(_ASM) */ + +#define STACK_GROWTH_DOWN /* stacks grow from high to low addresses */ + +#ifdef __cplusplus +} +#endif + +#endif /* _IA32_SYS_STACK_H */ diff --git a/module/icp/include/sys/ia32/trap.h b/module/icp/include/sys/ia32/trap.h new file mode 100644 index 000000000..55b94969b --- /dev/null +++ b/module/icp/include/sys/ia32/trap.h @@ -0,0 +1,107 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ +/* All Rights Reserved */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _IA32_SYS_TRAP_H +#define _IA32_SYS_TRAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Trap type values + */ + +#define T_ZERODIV 0x0 /* #de divide by 0 error */ +#define T_SGLSTP 0x1 /* #db single step */ +#define T_NMIFLT 0x2 /* NMI */ +#define T_BPTFLT 0x3 /* #bp breakpoint fault, INT3 insn */ +#define T_OVFLW 0x4 /* #of INTO overflow fault */ +#define T_BOUNDFLT 0x5 /* #br BOUND insn fault */ +#define T_ILLINST 0x6 /* #ud invalid opcode fault */ +#define T_NOEXTFLT 0x7 /* #nm device not available: x87 */ +#define T_DBLFLT 0x8 /* #df double fault */ +#define T_EXTOVRFLT 0x9 /* [not generated: 386 only] */ +#define T_TSSFLT 0xa /* #ts invalid TSS fault */ +#define T_SEGFLT 0xb /* #np segment not present fault */ +#define T_STKFLT 0xc /* #ss stack fault */ +#define T_GPFLT 0xd /* #gp general protection fault */ +#define T_PGFLT 0xe /* #pf page fault */ +#define T_EXTERRFLT 0x10 /* #mf x87 FPU error fault */ +#define T_ALIGNMENT 0x11 /* #ac alignment check error */ +#define T_MCE 0x12 /* #mc machine check exception */ +#define T_SIMDFPE 0x13 /* #xm SSE/SSE exception */ +#define T_DBGENTR 0x14 /* debugger entry */ +#define T_ENDPERR 0x21 /* emulated extension error flt */ +#define T_ENOEXTFLT 0x20 /* emulated ext not present */ +#define T_FASTTRAP 0xd2 /* fast system call */ +#define T_SYSCALLINT 0x91 /* general system call */ +#define T_DTRACE_RET 0x7f /* DTrace pid return */ +#define T_INT80 0x80 /* int80 handler for linux emulation */ +#define T_SOFTINT 0x50fd /* pseudo softint trap type */ + +/* + * Pseudo traps. + */ +#define T_INTERRUPT 0x100 +#define T_FAULT 0x200 +#define T_AST 0x400 +#define T_SYSCALL 0x180 + + +/* + * Values of error code on stack in case of page fault + */ + +#define PF_ERR_MASK 0x01 /* Mask for error bit */ +#define PF_ERR_PAGE 0x00 /* page not present */ +#define PF_ERR_PROT 0x01 /* protection error */ +#define PF_ERR_WRITE 0x02 /* fault caused by write (else read) */ +#define PF_ERR_USER 0x04 /* processor was in user mode */ + /* (else supervisor) */ +#define PF_ERR_EXEC 0x10 /* attempt to execute a No eXec page (AMD) */ + +/* + * Definitions for fast system call subfunctions + */ +#define T_FNULL 0 /* Null trap for testing */ +#define T_FGETFP 1 /* Get emulated FP context */ +#define T_FSETFP 2 /* Set emulated FP context */ +#define T_GETHRTIME 3 /* Get high resolution time */ +#define T_GETHRVTIME 4 /* Get high resolution virtual time */ +#define T_GETHRESTIME 5 /* Get high resolution time */ +#define T_GETLGRP 6 /* Get home lgrpid */ + +#define T_LASTFAST 6 /* Last valid subfunction */ + +#ifdef __cplusplus +} +#endif + +#endif /* _IA32_SYS_TRAP_H */ diff --git a/module/icp/include/sys/modctl.h b/module/icp/include/sys/modctl.h new file mode 100644 index 000000000..a0b94ef39 --- /dev/null +++ b/module/icp/include/sys/modctl.h @@ -0,0 +1,477 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_MODCTL_H +#define _SYS_MODCTL_H + +/* + * loadable module support. + */ + +#include <sys/zfs_context.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct modlmisc; +struct modlinkage; + +/* + * The following structure defines the operations used by modctl + * to load and unload modules. Each supported loadable module type + * requires a set of mod_ops. + */ +struct mod_ops { + int (*modm_install)(struct modlmisc *, struct modlinkage *); + int (*modm_remove)(struct modlmisc *, struct modlinkage *); + int (*modm_info)(void *, struct modlinkage *, int *); +}; + +/* + * The defined set of mod_ops structures for each loadable module type + * Defined in modctl.c + */ +extern struct mod_ops mod_brandops; +#if defined(__i386) || defined(__amd64) +extern struct mod_ops mod_cpuops; +#endif +extern struct mod_ops mod_cryptoops; +extern struct mod_ops mod_driverops; +extern struct mod_ops mod_execops; +extern struct mod_ops mod_fsops; +extern struct mod_ops mod_miscops; +extern struct mod_ops mod_schedops; +extern struct mod_ops mod_strmodops; +extern struct mod_ops mod_syscallops; +extern struct mod_ops mod_sockmodops; +#ifdef _SYSCALL32_IMPL +extern struct mod_ops mod_syscallops32; +#endif +extern struct mod_ops mod_dacfops; +extern struct mod_ops mod_ippops; +extern struct mod_ops mod_pcbeops; +extern struct mod_ops mod_devfsops; +extern struct mod_ops mod_kiconvops; + +/* + * Definitions for the module specific linkage structures. + * The first two fields are the same in all of the structures. + * The linkinfo is for informational purposes only and is returned by + * modctl with the MODINFO cmd. + */ + +/* For cryptographic providers */ +struct modlcrypto { + struct mod_ops *crypto_modops; + char *crypto_linkinfo; +}; + +/* For misc */ +struct modlmisc { + struct mod_ops *misc_modops; + char *misc_linkinfo; +}; + +/* + * Revision number of loadable modules support. This is the value + * that must be used in the modlinkage structure. + */ +#define MODREV_1 1 + +/* + * The modlinkage structure is the structure that the module writer + * provides to the routines to install, remove, and stat a module. + * The ml_linkage element is an array of pointers to linkage structures. + * For most modules there is only one linkage structure. We allocate + * enough space for 3 linkage structures which happens to be the most + * we have in any sun supplied module. For those modules with more + * than 3 linkage structures (which is very unlikely), a modlinkage + * structure must be kmem_alloc'd in the module wrapper to be big enough + * for all of the linkage structures. + */ +struct modlinkage { + int ml_rev; /* rev of loadable modules system */ +#ifdef _LP64 + void *ml_linkage[7]; /* more space in 64-bit OS */ +#else + void *ml_linkage[4]; /* NULL terminated list of */ + /* linkage structures */ +#endif +}; + +/* + * commands. These are the commands supported by the modctl system call. + */ +#define MODLOAD 0 +#define MODUNLOAD 1 +#define MODINFO 2 +#define MODRESERVED 3 +#define MODSETMINIROOT 4 +#define MODADDMAJBIND 5 +#define MODGETPATH 6 +#define MODREADSYSBIND 7 +#define MODGETMAJBIND 8 +#define MODGETNAME 9 +#define MODSIZEOF_DEVID 10 +#define MODGETDEVID 11 +#define MODSIZEOF_MINORNAME 12 +#define MODGETMINORNAME 13 +#define MODGETPATHLEN 14 +#define MODEVENTS 15 +#define MODGETFBNAME 16 +#define MODREREADDACF 17 +#define MODLOADDRVCONF 18 +#define MODUNLOADDRVCONF 19 +#define MODREMMAJBIND 20 +#define MODDEVT2INSTANCE 21 +#define MODGETDEVFSPATH_LEN 22 +#define MODGETDEVFSPATH 23 +#define MODDEVID2PATHS 24 +#define MODSETDEVPOLICY 26 +#define MODGETDEVPOLICY 27 +#define MODALLOCPRIV 28 +#define MODGETDEVPOLICYBYNAME 29 +#define MODLOADMINORPERM 31 +#define MODADDMINORPERM 32 +#define MODREMMINORPERM 33 +#define MODREMDRVCLEANUP 34 +#define MODDEVEXISTS 35 +#define MODDEVREADDIR 36 +#define MODDEVNAME 37 +#define MODGETDEVFSPATH_MI_LEN 38 +#define MODGETDEVFSPATH_MI 39 +#define MODRETIRE 40 +#define MODUNRETIRE 41 +#define MODISRETIRED 42 +#define MODDEVEMPTYDIR 43 +#define MODREMDRVALIAS 44 + +/* + * sub cmds for MODEVENTS + */ +#define MODEVENTS_FLUSH 0 +#define MODEVENTS_FLUSH_DUMP 1 +#define MODEVENTS_SET_DOOR_UPCALL_FILENAME 2 +#define MODEVENTS_GETDATA 3 +#define MODEVENTS_FREEDATA 4 +#define MODEVENTS_POST_EVENT 5 +#define MODEVENTS_REGISTER_EVENT 6 + +/* + * devname subcmds for MODDEVNAME + */ +#define MODDEVNAME_LOOKUPDOOR 0 +#define MODDEVNAME_DEVFSADMNODE 1 +#define MODDEVNAME_NSMAPS 2 +#define MODDEVNAME_PROFILE 3 +#define MODDEVNAME_RECONFIG 4 +#define MODDEVNAME_SYSAVAIL 5 + + +/* + * Data structure passed to modconfig command in kernel to build devfs tree + */ + +struct aliases { + struct aliases *a_next; + char *a_name; + int a_len; +}; + +#define MAXMODCONFNAME 256 + +struct modconfig { + char drvname[MAXMODCONFNAME]; + char drvclass[MAXMODCONFNAME]; + int major; + int flags; + int num_aliases; + struct aliases *ap; +}; + +#if defined(_SYSCALL32) + +struct aliases32 { + caddr32_t a_next; + caddr32_t a_name; + int32_t a_len; +}; + +struct modconfig32 { + char drvname[MAXMODCONFNAME]; + char drvclass[MAXMODCONFNAME]; + int32_t major; + int32_t flags; + int32_t num_aliases; + caddr32_t ap; +}; + +#endif /* _SYSCALL32 */ + +/* flags for modconfig */ +#define MOD_UNBIND_OVERRIDE 0x01 /* fail unbind if in use */ + +/* + * Max module path length + */ +#define MOD_MAXPATH 256 + +/* + * Default search path for modules ADDITIONAL to the directory + * where the kernel components we booted from are. + * + * Most often, this will be "/platform/{platform}/kernel /kernel /usr/kernel", + * but we don't wire it down here. + */ +#define MOD_DEFPATH "/kernel /usr/kernel" + +/* + * Default file name extension for autoloading modules. + */ +#define MOD_DEFEXT "" + +/* + * Parameters for modinfo + */ +#define MODMAXNAMELEN 32 /* max module name length */ +#define MODMAXLINKINFOLEN 32 /* max link info length */ + +/* + * Module specific information. + */ +struct modspecific_info { + char msi_linkinfo[MODMAXLINKINFOLEN]; /* name in linkage struct */ + int msi_p0; /* module specific information */ +}; + +/* + * Structure returned by modctl with MODINFO command. + */ +#define MODMAXLINK 10 /* max linkages modinfo can handle */ + +struct modinfo { + int mi_info; /* Flags for info wanted */ + int mi_state; /* Flags for module state */ + int mi_id; /* id of this loaded module */ + int mi_nextid; /* id of next module or -1 */ + caddr_t mi_base; /* virtual addr of text */ + size_t mi_size; /* size of module in bytes */ + int mi_rev; /* loadable modules rev */ + int mi_loadcnt; /* # of times loaded */ + char mi_name[MODMAXNAMELEN]; /* name of module */ + struct modspecific_info mi_msinfo[MODMAXLINK]; + /* mod specific info */ +}; + + +#if defined(_SYSCALL32) + +#define MODMAXNAMELEN32 32 /* max module name length */ +#define MODMAXLINKINFOLEN32 32 /* max link info length */ +#define MODMAXLINK32 10 /* max linkages modinfo can handle */ + +struct modspecific_info32 { + char msi_linkinfo[MODMAXLINKINFOLEN32]; /* name in linkage struct */ + int32_t msi_p0; /* module specific information */ +}; + +struct modinfo32 { + int32_t mi_info; /* Flags for info wanted */ + int32_t mi_state; /* Flags for module state */ + int32_t mi_id; /* id of this loaded module */ + int32_t mi_nextid; /* id of next module or -1 */ + caddr32_t mi_base; /* virtual addr of text */ + uint32_t mi_size; /* size of module in bytes */ + int32_t mi_rev; /* loadable modules rev */ + int32_t mi_loadcnt; /* # of times loaded */ + char mi_name[MODMAXNAMELEN32]; /* name of module */ + struct modspecific_info32 mi_msinfo[MODMAXLINK32]; + /* mod specific info */ +}; + +#endif /* _SYSCALL32 */ + +/* Values for mi_info flags */ +#define MI_INFO_ONE 1 +#define MI_INFO_ALL 2 +#define MI_INFO_CNT 4 +#define MI_INFO_LINKAGE 8 /* used internally to extract modlinkage */ +/* + * MI_INFO_NOBASE indicates caller does not need mi_base. Failure to use this + * flag may lead 32-bit apps to receive an EOVERFLOW error from modctl(MODINFO) + * when used with a 64-bit kernel. + */ +#define MI_INFO_NOBASE 16 + +/* Values for mi_state */ +#define MI_LOADED 1 +#define MI_INSTALLED 2 + +/* + * Macros to vector to the appropriate module specific routine. + */ +#define MODL_INSTALL(MODL, MODLP) \ + (*(MODL)->misc_modops->modm_install)(MODL, MODLP) +#define MODL_REMOVE(MODL, MODLP) \ + (*(MODL)->misc_modops->modm_remove)(MODL, MODLP) +#define MODL_INFO(MODL, MODLP, P0) \ + (*(MODL)->misc_modops->modm_info)(MODL, MODLP, P0) + +/* + * Definitions for stubs + */ +struct mod_stub_info { + uintptr_t mods_func_adr; + struct mod_modinfo *mods_modinfo; + uintptr_t mods_stub_adr; + int (*mods_errfcn)(void); + int mods_flag; /* flags defined below */ +}; + +/* + * Definitions for mods_flag. + */ +#define MODS_WEAK 0x01 /* weak stub (not loaded if called) */ +#define MODS_NOUNLOAD 0x02 /* module not unloadable (no _fini()) */ +#define MODS_INSTALLED 0x10 /* module installed */ + +struct mod_modinfo { + char *modm_module_name; + struct modctl *mp; + struct mod_stub_info modm_stubs[1]; +}; + +struct modctl_list { + struct modctl_list *modl_next; + struct modctl *modl_modp; +}; + +/* + * Structure to manage a loadable module. + * Note: the module (mod_mp) structure's "text" and "text_size" information + * are replicated in the modctl structure so that mod_containing_pc() + * doesn't have to grab any locks (modctls are persistent; modules are not.) + */ +typedef struct modctl { + struct modctl *mod_next; /* &modules based list */ + struct modctl *mod_prev; + int mod_id; + void *mod_mp; + kthread_t *mod_inprogress_thread; + struct mod_modinfo *mod_modinfo; + struct modlinkage *mod_linkage; + char *mod_filename; + char *mod_modname; + + char mod_busy; /* inprogress_thread has locked */ + char mod_want; /* someone waiting for unlock */ + char mod_prim; /* primary module */ + + int mod_ref; /* ref count - from dependent or stub */ + + char mod_loaded; /* module in memory */ + char mod_installed; /* post _init pre _fini */ + char mod_loadflags; + char mod_delay_unload; /* deferred unload */ + + struct modctl_list *mod_requisites; /* mods this one depends on. */ + void *__unused; /* NOTE: reuse (same size) is OK, */ + /* deletion causes mdb.vs.core issues */ + int mod_loadcnt; /* number of times mod was loaded */ + int mod_nenabled; /* # of enabled DTrace probes in mod */ + char *mod_text; + size_t mod_text_size; + + int mod_gencount; /* # times loaded/unloaded */ + struct modctl *mod_requisite_loading; /* mod circular dependency */ +} modctl_t; + +/* + * mod_loadflags + */ + +#define MOD_NOAUTOUNLOAD 0x1 /* Auto mod-unloader skips this mod */ +#define MOD_NONOTIFY 0x2 /* No krtld notifications on (un)load */ +#define MOD_NOUNLOAD 0x4 /* Assume EBUSY for all _fini's */ + +#define MOD_BIND_HASHSIZE 64 +#define MOD_BIND_HASHMASK (MOD_BIND_HASHSIZE-1) + +typedef int modid_t; + +/* + * global function and data declarations + */ +extern kmutex_t mod_lock; + +extern char *systemfile; +extern char **syscallnames; +extern int moddebug; + +/* + * this is the head of a doubly linked list. Only the next and prev + * pointers are used + */ +extern modctl_t modules; + +/* + * Only the following are part of the DDI/DKI + */ +extern int mod_install(struct modlinkage *); +extern int mod_remove(struct modlinkage *); +extern int mod_info(struct modlinkage *, struct modinfo *); + +/* + * bit definitions for moddebug. + */ +#define MODDEBUG_LOADMSG 0x80000000 /* print "[un]loading..." msg */ +#define MODDEBUG_ERRMSG 0x40000000 /* print detailed error msgs */ +#define MODDEBUG_LOADMSG2 0x20000000 /* print 2nd level msgs */ +#define MODDEBUG_RETIRE 0x10000000 /* print retire msgs */ +#define MODDEBUG_BINDING 0x00040000 /* driver/alias binding */ +#define MODDEBUG_FINI_EBUSY 0x00020000 /* pretend fini returns EBUSY */ +#define MODDEBUG_NOAUL_IPP 0x00010000 /* no Autounloading ipp mods */ +#define MODDEBUG_NOAUL_DACF 0x00008000 /* no Autounloading dacf mods */ +#define MODDEBUG_KEEPTEXT 0x00004000 /* keep text after unloading */ +#define MODDEBUG_NOAUL_DRV 0x00001000 /* no Autounloading Drivers */ +#define MODDEBUG_NOAUL_EXEC 0x00000800 /* no Autounloading Execs */ +#define MODDEBUG_NOAUL_FS 0x00000400 /* no Autounloading File sys */ +#define MODDEBUG_NOAUL_MISC 0x00000200 /* no Autounloading misc */ +#define MODDEBUG_NOAUL_SCHED 0x00000100 /* no Autounloading scheds */ +#define MODDEBUG_NOAUL_STR 0x00000080 /* no Autounloading streams */ +#define MODDEBUG_NOAUL_SYS 0x00000040 /* no Autounloading syscalls */ +#define MODDEBUG_NOCTF 0x00000020 /* do not load CTF debug data */ +#define MODDEBUG_NOAUTOUNLOAD 0x00000010 /* no autounloading at all */ +#define MODDEBUG_DDI_MOD 0x00000008 /* ddi_mod{open,sym,close} */ +#define MODDEBUG_MP_MATCH 0x00000004 /* dev_minorperm */ +#define MODDEBUG_MINORPERM 0x00000002 /* minor perm modctls */ +#define MODDEBUG_USERDEBUG 0x00000001 /* bpt after init_module() */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_MODCTL_H */ diff --git a/module/icp/include/sys/modhash.h b/module/icp/include/sys/modhash.h new file mode 100644 index 000000000..06b52ff02 --- /dev/null +++ b/module/icp/include/sys/modhash.h @@ -0,0 +1,147 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_MODHASH_H +#define _SYS_MODHASH_H + +/* + * Generic hash implementation for the kernel. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/zfs_context.h> + +/* + * Opaque data types for storing keys and values + */ +typedef void *mod_hash_val_t; +typedef void *mod_hash_key_t; + +/* + * Opaque data type for reservation + */ +typedef void *mod_hash_hndl_t; + +/* + * Opaque type for hash itself. + */ +struct mod_hash; +typedef struct mod_hash mod_hash_t; + +/* + * String hash table + */ +mod_hash_t *mod_hash_create_strhash_nodtr(char *, size_t, + void (*)(mod_hash_val_t)); +mod_hash_t *mod_hash_create_strhash(char *, size_t, void (*)(mod_hash_val_t)); +void mod_hash_destroy_strhash(mod_hash_t *); +int mod_hash_strkey_cmp(mod_hash_key_t, mod_hash_key_t); +void mod_hash_strkey_dtor(mod_hash_key_t); +void mod_hash_strval_dtor(mod_hash_val_t); +uint_t mod_hash_bystr(void *, mod_hash_key_t); + +/* + * Pointer hash table + */ +mod_hash_t *mod_hash_create_ptrhash(char *, size_t, void (*)(mod_hash_val_t), + size_t); +void mod_hash_destroy_ptrhash(mod_hash_t *); +int mod_hash_ptrkey_cmp(mod_hash_key_t, mod_hash_key_t); +uint_t mod_hash_byptr(void *, mod_hash_key_t); + +/* + * ID hash table + */ +mod_hash_t *mod_hash_create_idhash(char *, size_t, void (*)(mod_hash_val_t)); +void mod_hash_destroy_idhash(mod_hash_t *); +int mod_hash_idkey_cmp(mod_hash_key_t, mod_hash_key_t); +uint_t mod_hash_byid(void *, mod_hash_key_t); +uint_t mod_hash_iddata_gen(size_t); + +/* + * Hash management functions + */ +mod_hash_t *mod_hash_create_extended(char *, size_t, void (*)(mod_hash_key_t), + void (*)(mod_hash_val_t), uint_t (*)(void *, mod_hash_key_t), void *, + int (*)(mod_hash_key_t, mod_hash_key_t), int); + +void mod_hash_destroy_hash(mod_hash_t *); +void mod_hash_clear(mod_hash_t *); + +/* + * Null key and value destructors + */ +void mod_hash_null_keydtor(mod_hash_key_t); +void mod_hash_null_valdtor(mod_hash_val_t); + +/* + * Basic hash operations + */ + +/* + * Error codes for insert, remove, find, destroy. + */ +#define MH_ERR_NOMEM -1 +#define MH_ERR_DUPLICATE -2 +#define MH_ERR_NOTFOUND -3 + +/* + * Return codes for hash walkers + */ +#define MH_WALK_CONTINUE 0 +#define MH_WALK_TERMINATE 1 + +/* + * Basic hash operations + */ +int mod_hash_insert(mod_hash_t *, mod_hash_key_t, mod_hash_val_t); +int mod_hash_replace(mod_hash_t *, mod_hash_key_t, mod_hash_val_t); +int mod_hash_remove(mod_hash_t *, mod_hash_key_t, mod_hash_val_t *); +int mod_hash_destroy(mod_hash_t *, mod_hash_key_t); +int mod_hash_find(mod_hash_t *, mod_hash_key_t, mod_hash_val_t *); +int mod_hash_find_cb(mod_hash_t *, mod_hash_key_t, mod_hash_val_t *, + void (*)(mod_hash_key_t, mod_hash_val_t)); +int mod_hash_find_cb_rval(mod_hash_t *, mod_hash_key_t, mod_hash_val_t *, + int (*)(mod_hash_key_t, mod_hash_val_t), int *); +void mod_hash_walk(mod_hash_t *, + uint_t (*)(mod_hash_key_t, mod_hash_val_t *, void *), void *); + +/* + * Reserving hash operations + */ +int mod_hash_reserve(mod_hash_t *, mod_hash_hndl_t *); +int mod_hash_reserve_nosleep(mod_hash_t *, mod_hash_hndl_t *); +void mod_hash_cancel(mod_hash_t *, mod_hash_hndl_t *); +int mod_hash_insert_reserve(mod_hash_t *, mod_hash_key_t, mod_hash_val_t, + mod_hash_hndl_t); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_MODHASH_H */ diff --git a/module/icp/include/sys/modhash_impl.h b/module/icp/include/sys/modhash_impl.h new file mode 100644 index 000000000..3130773aa --- /dev/null +++ b/module/icp/include/sys/modhash_impl.h @@ -0,0 +1,108 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_MODHASH_IMPL_H +#define _SYS_MODHASH_IMPL_H + +/* + * Internal details for the kernel's generic hash implementation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/zfs_context.h> +#include <sys/modhash.h> + +struct mod_hash_entry { + mod_hash_key_t mhe_key; /* stored hash key */ + mod_hash_val_t mhe_val; /* stored hash value */ + struct mod_hash_entry *mhe_next; /* next item in chain */ +}; + +struct mod_hash_stat { + ulong_t mhs_hit; /* tried a 'find' and it succeeded */ + ulong_t mhs_miss; /* tried a 'find' but it failed */ + ulong_t mhs_coll; /* occur when insert fails because of dup's */ + ulong_t mhs_nelems; /* total number of stored key/value pairs */ + ulong_t mhs_nomem; /* number of times kmem_alloc failed */ +}; + +struct mod_hash { + krwlock_t mh_contents; /* lock protecting contents */ + char *mh_name; /* hash name */ + int mh_sleep; /* kmem_alloc flag */ + size_t mh_nchains; /* # of elements in mh_entries */ + + /* key and val destructor */ + void (*mh_kdtor)(mod_hash_key_t); + void (*mh_vdtor)(mod_hash_val_t); + + /* key comparator */ + int (*mh_keycmp)(mod_hash_key_t, mod_hash_key_t); + + /* hash algorithm, and algorithm-private data */ + uint_t (*mh_hashalg)(void *, mod_hash_key_t); + void *mh_hashalg_data; + + struct mod_hash *mh_next; /* next hash in list */ + + struct mod_hash_stat mh_stat; + + struct mod_hash_entry *mh_entries[1]; +}; + +/* + * MH_SIZE() + * Compute the size of a mod_hash_t, in bytes, given the number of + * elements it contains. + */ +#define MH_SIZE(n) \ + (sizeof (mod_hash_t) + ((n) - 1) * (sizeof (struct mod_hash_entry *))) + +/* + * Module initialization; called once. + */ +void mod_hash_fini(void); +void mod_hash_init(void); + +/* + * Internal routines. Use directly with care. + */ +uint_t i_mod_hash(mod_hash_t *, mod_hash_key_t); +int i_mod_hash_insert_nosync(mod_hash_t *, mod_hash_key_t, mod_hash_val_t, + mod_hash_hndl_t); +int i_mod_hash_remove_nosync(mod_hash_t *, mod_hash_key_t, mod_hash_val_t *); +int i_mod_hash_find_nosync(mod_hash_t *, mod_hash_key_t, mod_hash_val_t *); +void i_mod_hash_walk_nosync(mod_hash_t *, uint_t (*)(mod_hash_key_t, + mod_hash_val_t *, void *), void *); +void i_mod_hash_clear_nosync(mod_hash_t *hash); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_MODHASH_IMPL_H */ diff --git a/module/icp/include/sys/stack.h b/module/icp/include/sys/stack.h new file mode 100644 index 000000000..64fecf409 --- /dev/null +++ b/module/icp/include/sys/stack.h @@ -0,0 +1,36 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_STACK_H +#define _SYS_STACK_H + +#if defined(__i386) || defined(__amd64) + +#include <sys/ia32/stack.h> /* XX64 x86/sys/stack.h */ + +#endif + +#endif /* _SYS_STACK_H */ diff --git a/module/icp/include/sys/trap.h b/module/icp/include/sys/trap.h new file mode 100644 index 000000000..7f9fd3758 --- /dev/null +++ b/module/icp/include/sys/trap.h @@ -0,0 +1,36 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_TRAP_H +#define _SYS_TRAP_H + +#if defined(__i386) || defined(__amd64) + +#include <sys/ia32/trap.h> /* XX64 x86/sys/trap.h */ + +#endif + +#endif /* _SYS_TRAP_H */ |