4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * CDDL HEADER START
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * The contents of this file are subject to the terms of the
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Common Development and Distribution License (the "License").
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * You may not use this file except in compliance with the License.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * See the License for the specific language governing permissions
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * and limitations under the License.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * When distributing Covered Code, include this CDDL HEADER in each
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * If applicable, add the following below this CDDL HEADER, with the
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * fields enclosed by brackets "[]" replaced with your own identifying
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * information: Portions Copyright [yyyy] [name of copyright owner]
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * CDDL HEADER END
7417cfdecea1902cef03c0d61a72df97d945925dKuriakose Kuruvilla * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#endif /* _KERNEL */
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#include <sys/cpuvar.h> /* cpu_t, CPU */
7417cfdecea1902cef03c0d61a72df97d945925dKuriakose Kuruvilla#include <sys/x86_archext.h> /* x86_featureset, X86FSET_*, CPUID_* */
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#include <sys/disp.h> /* kpreempt_disable(), kpreempt_enable */
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson/* Workaround for no XMM kernel thread save/restore */
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#define KPREEMPT_DISABLE kpreempt_disable()
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#define KPREEMPT_ENABLE kpreempt_enable()
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#include <sys/auxv.h> /* getisax() */
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#include <sys/auxv_386.h> /* AV_386_PCLMULQDQ bit */
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#endif /* _KERNEL */
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Andersonextern void gcm_mul_pclmulqdq(uint64_t *x_in, uint64_t *y, uint64_t *res);
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Andersonstatic int intel_pclmulqdq_instruction_present(void);
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#endif /* __amd64 */
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson * Perform a carry-less multiplication (that is, use XOR instead of the
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson * multiply operator) on *x_in and *y and place the result in *res.
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson * Byte swap the input (*x_in and *y) and the output (*res).
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson * Note: x_in, y, and res all point to 16-byte numbers (an array of two
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson * 64-bit integers).
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powersgcm_mul(uint64_t *x_in, uint64_t *y, uint64_t *res)
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson if (intel_pclmulqdq_instruction_present()) {
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#endif /* __amd64 */
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson static const uint64_t R = 0xe100000000000000ULL;
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson struct aes_block z = {0, 0};
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson for (j = 0; j < 2; j++) {
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson for (i = 0; i < 64; i++, x <<= 1) {
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson if (x & 0x8000000000000000ULL) {
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson if (v.b & 1ULL) {
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson v.a = (v.a >> 1) ^ R;
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson v.a = v.a >> 1;
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers xor_block((uint8_t *)(d), (uint8_t *)(c)->gcm_ghash); \
95014fbbfdc010ab9f3ed20db2154dc3322e9270Dan OpenSolaris Anderson gcm_mul((uint64_t *)(void *)(c)->gcm_ghash, (c)->gcm_H, \
95014fbbfdc010ab9f3ed20db2154dc3322e9270Dan OpenSolaris Anderson (uint64_t *)(void *)(t));
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Encrypt multiple blocks of data in GCM mode. Decrypt for GCM mode
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * is done in another function.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powersgcm_mode_encrypt_contiguous_blocks(gcm_ctx_t *ctx, char *data, size_t length,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers uint64_t counter_mask = ntohll(0x00000000ffffffffULL);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers if (length + ctx->gcm_remainder_len < block_size) {
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* accumulate bytes here and return */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers (uint8_t *)ctx->gcm_remainder + ctx->gcm_remainder_len,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* Unprocessed data from last call. */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Increment counter. Counter bits are confined
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * to the bottom 32 bits of the counter block.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers counter = ntohll(ctx->gcm_cb[1] & counter_mask);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers ctx->gcm_cb[1] = (ctx->gcm_cb[1] & ~counter_mask) | counter;
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers encrypt_block(ctx->gcm_keysched, (uint8_t *)ctx->gcm_cb,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* copy block to where it belongs */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* update offset */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* add ciphertext to the hash */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* Update pointer to next block of data to be processed. */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers remainder = (size_t)&data[length] - (size_t)datap;
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* Incomplete last block. */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers } while (remainder > 0);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers/* ARGSUSED */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powersgcm_encrypt_final(gcm_ctx_t *ctx, crypto_data_t *out, size_t block_size,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers uint64_t counter_mask = ntohll(0x00000000ffffffffULL);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Here is where we deal with data that is not a
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * multiple of the block size.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Increment counter.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers counter = ntohll(ctx->gcm_cb[1] & counter_mask);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers ctx->gcm_cb[1] = (ctx->gcm_cb[1] & ~counter_mask) | counter;
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers encrypt_block(ctx->gcm_keysched, (uint8_t *)ctx->gcm_cb,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* XOR with counter block */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* add ciphertext to the hash */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers ctx->gcm_processed_data_len += ctx->gcm_remainder_len;
95014fbbfdc010ab9f3ed20db2154dc3322e9270Dan OpenSolaris Anderson htonll(CRYPTO_BYTES2BITS(ctx->gcm_processed_data_len));
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers encrypt_block(ctx->gcm_keysched, (uint8_t *)ctx->gcm_J0,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers rv = crypto_put_output_data(macp, out, ctx->gcm_remainder_len);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers rv = crypto_put_output_data(ghash, out, ctx->gcm_tag_len);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * This will only deal with decrypting the last block of the input that
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * might not be a multiple of block length.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powersgcm_decrypt_incomplete_block(gcm_ctx_t *ctx, size_t block_size, size_t index,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers uint64_t counter_mask = ntohll(0x00000000ffffffffULL);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Increment counter.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Counter bits are confined to the bottom 32 bits
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers counter = ntohll(ctx->gcm_cb[1] & counter_mask);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers ctx->gcm_cb[1] = (ctx->gcm_cb[1] & ~counter_mask) | counter;
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* authentication tag */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers bcopy(datap, (uint8_t *)ctx->gcm_tmp, ctx->gcm_remainder_len);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* add ciphertext to the hash */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* decrypt remaining ciphertext */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers encrypt_block(ctx->gcm_keysched, (uint8_t *)ctx->gcm_cb, counterp);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* XOR with counter block */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers/* ARGSUSED */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powersgcm_mode_decrypt_contiguous_blocks(gcm_ctx_t *ctx, char *data, size_t length,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Copy contiguous ciphertext input blocks to plaintext buffer.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Ciphertext will be decrypted in the final.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers bcopy(ctx->gcm_pt_buf, new, ctx->gcm_pt_buf_len);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers kmem_free(ctx->gcm_pt_buf, ctx->gcm_pt_buf_len);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers bcopy(ctx->gcm_pt_buf, new, ctx->gcm_pt_buf_len);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers bcopy(data, &ctx->gcm_pt_buf[ctx->gcm_processed_data_len],
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powersgcm_decrypt_final(gcm_ctx_t *ctx, crypto_data_t *out, size_t block_size,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers uint64_t counter_mask = ntohll(0x00000000ffffffffULL);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers ASSERT(ctx->gcm_processed_data_len == ctx->gcm_pt_buf_len);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers pt_len = ctx->gcm_processed_data_len - ctx->gcm_tag_len;
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers while (remainder > 0) {
553d52d4675c67a5de5a10ad30305be1a208e218Mark Fenwick /* Incomplete last block */
553d52d4675c67a5de5a10ad30305be1a208e218Mark Fenwick * not expecting anymore ciphertext, just
553d52d4675c67a5de5a10ad30305be1a208e218Mark Fenwick * compute plaintext for the remaining input
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* add ciphertext to the hash */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Increment counter.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Counter bits are confined to the bottom 32 bits
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers counter = ntohll(ctx->gcm_cb[1] & counter_mask);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers ctx->gcm_cb[1] = (ctx->gcm_cb[1] & ~counter_mask) | counter;
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers encrypt_block(ctx->gcm_keysched, (uint8_t *)ctx->gcm_cb, cbp);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* XOR with ciphertext */
95014fbbfdc010ab9f3ed20db2154dc3322e9270Dan OpenSolaris Anderson ctx->gcm_len_a_len_c[1] = htonll(CRYPTO_BYTES2BITS(pt_len));
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers encrypt_block(ctx->gcm_keysched, (uint8_t *)ctx->gcm_J0,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* compare the input authentication tag with what we calculated */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers if (bcmp(&ctx->gcm_pt_buf[pt_len], ghash, ctx->gcm_tag_len)) {
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* They don't match */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers rv = crypto_put_output_data(ctx->gcm_pt_buf, out, pt_len);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * Check the length of the authentication tag (in bits).
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powersgcm_format_initial_blocks(uchar_t *iv, ulong_t iv_len,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* J0 will be used again in the final */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* GHASH the IV */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers } while (remainder > 0);
95014fbbfdc010ab9f3ed20db2154dc3322e9270Dan OpenSolaris Anderson len_a_len_c[1] = htonll(CRYPTO_BYTES2BITS(iv_len));
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* J0 will be used again in the final */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers copy_block((uint8_t *)ctx->gcm_J0, (uint8_t *)cb);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * The following function is called at encrypt or decrypt init time
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * for AES GCM mode.
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powersgcm_init(gcm_ctx_t *ctx, unsigned char *iv, size_t iv_len,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers unsigned char *auth_data, size_t auth_data_len, size_t block_size,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* encrypt zero block to get subkey H */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers encrypt_block(ctx->gcm_keysched, (uint8_t *)ctx->gcm_H,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers gcm_format_initial_blocks(iv, iv_len, ctx, block_size,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * There's not a block full of data, pad rest of
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers * buffer with zero
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers bcopy(&(auth_data[processed]), authp, remainder);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* add auth data to the hash */
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers } while (remainder > 0);
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powersgcm_init_ctx(gcm_ctx_t *gcm_ctx, char *param, size_t block_size,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
95014fbbfdc010ab9f3ed20db2154dc3322e9270Dan OpenSolaris Anderson gcm_param = (CK_AES_GCM_PARAMS *)(void *)param;
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers /* these values are in bits */
95014fbbfdc010ab9f3ed20db2154dc3322e9270Dan OpenSolaris Anderson = htonll(CRYPTO_BYTES2BITS(gcm_param->ulAADLen));
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers if (gcm_init(gcm_ctx, gcm_param->pIv, gcm_param->ulIvLen,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers gcm_param->pAAD, gcm_param->ulAADLen, block_size,
983a10335731bc55a0b7a37f195575fa109e30d4Mark Powersgmac_init_ctx(gcm_ctx_t *gcm_ctx, char *param, size_t block_size,
983a10335731bc55a0b7a37f195575fa109e30d4Mark Powers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
95014fbbfdc010ab9f3ed20db2154dc3322e9270Dan OpenSolaris Anderson gmac_param = (CK_AES_GMAC_PARAMS *)(void *)param;
983a10335731bc55a0b7a37f195575fa109e30d4Mark Powers gcm_ctx->gcm_tag_len = CRYPTO_BITS2BYTES(AES_GMAC_TAG_BITS);
983a10335731bc55a0b7a37f195575fa109e30d4Mark Powers /* these values are in bits */
95014fbbfdc010ab9f3ed20db2154dc3322e9270Dan OpenSolaris Anderson = htonll(CRYPTO_BYTES2BITS(gmac_param->ulAADLen));
983a10335731bc55a0b7a37f195575fa109e30d4Mark Powers if (gcm_init(gcm_ctx, gmac_param->pIv, AES_GMAC_IV_LEN,
983a10335731bc55a0b7a37f195575fa109e30d4Mark Powers gmac_param->pAAD, gmac_param->ulAADLen, block_size,
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers if ((gcm_ctx = kmem_zalloc(sizeof (gcm_ctx_t), kmflag)) == NULL)
4d703b5c9cb1bc29ace6c53cb50b2fe766e6370fMark Powers if ((gcm_ctx = calloc(1, sizeof (gcm_ctx_t))) == NULL)
983a10335731bc55a0b7a37f195575fa109e30d4Mark Powers if ((gcm_ctx = kmem_zalloc(sizeof (gcm_ctx_t), kmflag)) == NULL)
983a10335731bc55a0b7a37f195575fa109e30d4Mark Powers if ((gcm_ctx = calloc(1, sizeof (gcm_ctx_t))) == NULL)
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson * Return 1 if executing on Intel with PCLMULQDQ instructions,
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson * otherwise 0 (i.e., Intel without PCLMULQDQ or AMD64).
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson * Cache the result, as the CPU can't change.
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson * Note: the userland version uses getisax(). The kernel version uses
7417cfdecea1902cef03c0d61a72df97d945925dKuriakose Kuruvilla * is_x86_featureset().
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Andersonintel_pclmulqdq_instruction_present(void)
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson if (cached_result == -1) { /* first time */
7417cfdecea1902cef03c0d61a72df97d945925dKuriakose Kuruvilla is_x86_feature(x86_featureset, X86FSET_PCLMULQDQ);
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson cached_result = (ui & AV_386_PCLMULQDQ) != 0;
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#endif /* _KERNEL */
104d3bde5b4ac46904f144d3676110fc57a69603Dan OpenSolaris Anderson#endif /* __amd64 */