示例#1
0
/*!
 * Place a key into a protected location for use only by cryptographic
 * algorithms.
 *
 * This only needs to be used to a) unwrap a key, or b) set up a key which
 * could be wrapped with a later call to #fsl_shw_extract_key().  Normal
 * cleartext keys can simply be placed into #fsl_shw_sko_t key objects with
 * #fsl_shw_sko_set_key() and used directly.
 *
 * The maximum key size supported for wrapped/unwrapped keys is 32 octets.
 * (This is the maximum reasonable key length on Sahara - 32 octets for an HMAC
 * key based on SHA-256.)  The key size is determined by the @a key_info.  The
 * expected length of @a key can be determined by
 * #fsl_shw_sko_calculate_wrapped_size()
 *
 * The protected key will not be available for use until this operation
 * successfully completes.
 *
 * This feature is not available for all platforms, nor for all algorithms and
 * modes.
 *
 * @param      user_ctx         A user context from #fsl_shw_register_user().
 * @param[in,out] key_info      The information about the key to be which will
 *                              be established.  In the create case, the key
 *                              length must be set.
 * @param      establish_type   How @a key will be interpreted to establish a
 *                              key for use.
 * @param key                   If @a establish_type is #FSL_KEY_WRAP_UNWRAP,
 *                              this is the location of a wrapped key.  If
 *                              @a establish_type is #FSL_KEY_WRAP_CREATE, this
 *                              parameter can be @a NULL.  If @a establish_type
 *                              is #FSL_KEY_WRAP_ACCEPT, this is the location
 *                              of a plaintext key.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_establish_key(fsl_shw_uco_t * user_ctx,
				       fsl_shw_sko_t * key_info,
				       fsl_shw_key_wrap_t establish_type,
				       const uint8_t * key)
{
	fsl_shw_return_t ret;
	sah_Head_Desc *desc_chain = NULL;
	uint32_t header = SAH_HDR_RNG_GENERATE;	/* Desc. #18 for rand */
	unsigned original_key_length = key_info->key_length;
	unsigned rounded_key_length;

	/* Write operations into SCC memory require word-multiple number of
	 * bytes.  For ACCEPT and CREATE functions, the key length may need
	 * to be rounded up.  Calculate. */
	if ((original_key_length & 3) != 0) {
		rounded_key_length = original_key_length + 4
		    - (original_key_length & 3);
	} else {
		rounded_key_length = original_key_length;
	}

	/* perform sanity check on the uco */
	ret = sah_validate_uco(user_ctx);
	if (ret != FSL_RETURN_OK_S) {
		return ret;
	}

	ret =
	    do_scc_slot_alloc(user_ctx, key_info->key_length, key_info->userid,
			      &key_info->handle);

	if (ret == FSL_RETURN_OK_S) {
		key_info->flags |= FSL_SKO_KEY_ESTABLISHED;
		switch (establish_type) {
		case FSL_KEY_WRAP_CREATE:
			/* Use safe version of key length */
			key_info->key_length = rounded_key_length;
			/* Generate descriptor to put random value into */
			ret = add_key_out_desc(header, key_info, NULL, 0,
					       user_ctx->mem_util, &desc_chain);
			/* Restore actual, desired key length */
			key_info->key_length = original_key_length;

			if (ret == FSL_RETURN_OK_S) {
				uint32_t old_flags = user_ctx->flags;

				/* Now put random value into key */
				ret =
				    sah_Descriptor_Chain_Execute(desc_chain,
								 user_ctx);
				/* Restore user's old flag value */
				user_ctx->flags = old_flags;
			}
#ifdef DIAG_SECURITY_FUNC
			else {
				LOG_DIAG
				    ("Creation of sah_Key_Link failed due to bad"
				     " key flag!\n");
			}
#endif				/*DIAG_SECURITY_FUNC */
			break;

		case FSL_KEY_WRAP_ACCEPT:
			if (key == NULL) {
#ifdef DIAG_SECURITY_FUNC
				LOG_DIAG("ACCEPT:  Red Key is NULL");
#endif
				ret = FSL_RETURN_ERROR_S;
			} else {
				/* Copy in safe number of bytes of Red key */
				ret =
				    do_scc_slot_load_slot(user_ctx,
							  key_info->userid,
							  key_info->handle, key,
							  rounded_key_length);
			}
			break;

		case FSL_KEY_WRAP_UNWRAP:
			/* For now, disallow non-blocking calls. */
			if (!(user_ctx->flags & FSL_UCO_BLOCKING_MODE)) {
				ret = FSL_RETURN_BAD_FLAG_S;
			} else if (key == NULL) {
				ret = FSL_RETURN_ERROR_S;
			} else {
				ret = unwrap(user_ctx, key_info, key);
				if (ret != FSL_RETURN_OK_S) {
				}
			}
			break;

		default:
			ret = FSL_RETURN_BAD_FLAG_S;
			break;
		}		/* switch */

		if (ret != FSL_RETURN_OK_S) {
			fsl_shw_return_t scc_err;
			scc_err =
			    do_scc_slot_dealloc(user_ctx, key_info->userid,
						key_info->handle);
			key_info->flags &= ~FSL_SKO_KEY_ESTABLISHED;
		}
	}

	return ret;
}
示例#2
0
/*!
 * Perform wrapping of a black key from a RED slot
 *
 * @param      user_ctx         A user context from #fsl_shw_register_user().
 * @param[in,out] key_info      The information about the key to be which will
 *                              be wrapped... key length, slot info, etc.
 * @param      black_key        Place to store encrypted key
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
static fsl_shw_return_t wrap(fsl_shw_uco_t * user_ctx,
			     fsl_shw_sko_t * key_info, uint8_t * black_key)
{
	fsl_shw_return_t ret;
	sah_Head_Desc *desc_chain = NULL;
	unsigned slots_allocated = 0;	/* boolean */
	fsl_shw_sko_t T_key_info;	/* for holding T */
	fsl_shw_sko_t KEK_key_info;	/* for holding KEK */

	black_key[LENGTH_OFFSET] = key_info->key_length;
	black_key[ALGORITHM_OFFSET] = key_info->algorithm;

	memcpy(&T_key_info, key_info, sizeof(T_key_info));
	fsl_shw_sko_set_key_length(&T_key_info, T_LENGTH);
	T_key_info.algorithm = FSL_KEY_ALG_HMAC;

	memcpy(&KEK_key_info, &T_key_info, sizeof(KEK_key_info));
	KEK_key_info.algorithm = FSL_KEY_ALG_AES;

	ret = do_scc_slot_alloc(user_ctx, T_LENGTH, key_info->userid,
				&T_key_info.handle);

	if (ret == FSL_RETURN_OK_S) {
		ret = do_scc_slot_alloc(user_ctx, KEK_LENGTH, key_info->userid,
					&KEK_key_info.handle);
		if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
			LOG_DIAG("do_scc_slot_alloc() failed");
#endif
			do_scc_slot_dealloc(user_ctx, key_info->userid,
					    T_key_info.handle);
		} else {
			slots_allocated = 1;
		}

	}

	/* Set up to compute everything except T' ... */
	if (ret == FSL_RETURN_OK_S) {
		uint32_t header;

#ifndef DO_REPEATABLE_WRAP
		/* Compute T = RND() */
		header = SAH_HDR_RNG_GENERATE;	/* Desc. #18 */
		ret = add_key_out_desc(header, &T_key_info, NULL, 0,
				       user_ctx->mem_util, &desc_chain);
#else
		ret = do_scc_slot_load_slot(user_ctx, T_key_info.userid,
					    T_key_info.handle, T_block,
					    T_key_info.key_length);
#endif

		/* Compute KEK = SHA1(T | Ownerid) */
		if (ret == FSL_RETURN_OK_S) {
			sah_Link *link1;
			sah_Link *link2;

			header = (SAH_HDR_MDHA_SET_MODE_HASH	/* #8 */
				  ^ insert_mdha_init
				  ^ insert_mdha_algorithm[FSL_HASH_ALG_SHA1]
				  ^ insert_mdha_pdata);

			/* Input - Start with T */
			ret =
			    sah_Create_Key_Link(user_ctx->mem_util, &link1,
						&T_key_info);

			if (ret == FSL_RETURN_OK_S) {
				/* Still input - append ownerid */
				ret = sah_Append_Link(user_ctx->mem_util, link1,
						      (void *)&key_info->userid,
						      sizeof(key_info->userid),
						      SAH_USES_LINK_DATA);
			}

			if (ret == FSL_RETURN_OK_S) {
				/* Output - KEK goes into RED slot */
				ret =
				    sah_Create_Key_Link(user_ctx->mem_util,
							&link2, &KEK_key_info);
			}

			/* Put the Hash calculation into the chain. */
			if (ret == FSL_RETURN_OK_S) {
				ret =
				    sah_Append_Desc(user_ctx->mem_util,
						    &desc_chain, header, link1,
						    link2);
			}
		}

		/* Compute KEY' = AES-encrypt(KEK, KEY) */
		if (ret == FSL_RETURN_OK_S) {

			header = (SAH_HDR_SKHA_SET_MODE_IV_KEY	/* #1 */
				  ^ insert_skha_mode[FSL_SYM_MODE_CTR]
				  ^ insert_skha_algorithm[FSL_KEY_ALG_AES]
				  ^ insert_skha_modulus[FSL_CTR_MOD_128]);
			/* Set up KEK as key to use */
			ret = add_in_key_desc(header, NULL, 0, &KEK_key_info,
					      user_ctx->mem_util, &desc_chain);

			/* Set up KEY as input, KEY' as output */
			if (ret == FSL_RETURN_OK_S) {
				header = SAH_HDR_SKHA_ENC_DEC;	/* #4 */
				ret = add_key_out_desc(header, key_info,
						       black_key +
						       KEY_PRIME_OFFSET,
						       key_info->key_length,
						       user_ctx->mem_util,
						       &desc_chain);
			}
#ifdef DIAG_SECURITY_FUNC
			if (ret != FSL_RETURN_OK_S) {
				LOG_DIAG
				    ("Creation of sah_Key_Link failed due to bad key"
				     " flag!\n");
			}
#endif				/*DIAG_SECURITY_FUNC */
		}

		/* Compute and store ICV into Black Key */
		if (ret == FSL_RETURN_OK_S) {
			ret =
			    create_icv_calc(user_ctx, &desc_chain, &T_key_info,
					    black_key, key_info->key_length,
					    black_key + ICV_OFFSET);
#ifdef DIAG_SECURITY_FUNC
			if (ret != FSL_RETURN_OK_S) {
				LOG_DIAG
				    ("Creation of sah_Key_Link failed due to bad key"
				     " flag!\n");
			}
#endif				/*DIAG_SECURITY_FUNC */
		}
	}

	/* Now get Sahara to do the work. */
	if (ret == FSL_RETURN_OK_S) {
		ret = sah_Descriptor_Chain_Execute(desc_chain, user_ctx);
#ifdef DIAG_SECURITY_FUNC
		if (ret != FSL_RETURN_OK_S) {
			LOG_DIAG("sah_Descriptor_Chain_Execute() failed");
		}
#endif
	}

	/* Compute T' = SLID_encrypt(T); Result goes to Black Key */
	if (ret == FSL_RETURN_OK_S) {
		ret = do_scc_slot_encrypt(user_ctx, T_key_info.userid,
					  T_key_info.handle,
					  T_LENGTH, black_key + T_PRIME_OFFSET);
#ifdef DIAG_SECURITY_FUNC
		if (ret != FSL_RETURN_OK_S) {
			LOG_DIAG("do_scc_slot_encrypt() failed");
		}
#endif
	}

	if (slots_allocated) {
		do_scc_slot_dealloc(user_ctx, key_info->userid,
				    T_key_info.handle);
		do_scc_slot_dealloc(user_ctx, key_info->userid,
				    KEK_key_info.handle);
	}

	return ret;
}				/* wrap */
示例#3
0
/*!
 * Perform unwrapping of a black key into a RED slot
 *
 * @param         user_ctx      A user context from #fsl_shw_register_user().
 * @param[in,out] key_info      The information about the key to be which will
 *                              be unwrapped... key length, slot info, etc.
 * @param         black_key     Encrypted key
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
static fsl_shw_return_t unwrap(fsl_shw_uco_t * user_ctx,
			       fsl_shw_sko_t * key_info,
			       const uint8_t * black_key)
{
	fsl_shw_return_t ret = FSL_RETURN_ERROR_S;
	sah_Mem_Util *mu = user_ctx->mem_util;
	uint8_t *hmac = mu->mu_malloc(mu->mu_ref, ICV_LENGTH);

	if (hmac == NULL) {
		ret = FSL_RETURN_NO_RESOURCE_S;
	} else {
		sah_Head_Desc *desc_chain = NULL;
		fsl_shw_sko_t t_key_info;
		unsigned i;

		/* Set up key_info for "T" - use same slot as eventual key */
		fsl_shw_sko_init(&t_key_info, FSL_KEY_ALG_AES);
		t_key_info.userid = key_info->userid;
		t_key_info.handle = key_info->handle;
		t_key_info.flags = key_info->flags;
		t_key_info.key_length = T_LENGTH;

		/* Compute T = SLID_decrypt(T'); leave in RED slot */
		ret = do_scc_slot_decrypt(user_ctx, key_info->userid,
					  t_key_info.handle,
					  T_LENGTH, black_key + T_PRIME_OFFSET);

		/* Compute ICV = HMAC(T, ownerid | len | alg | key' */
		if (ret == FSL_RETURN_OK_S) {
			ret =
			    create_icv_calc(user_ctx, &desc_chain, &t_key_info,
					    black_key, key_info->key_length,
					    hmac);
			if (ret == FSL_RETURN_OK_S) {
				ret =
				    sah_Descriptor_Chain_Execute(desc_chain,
								 user_ctx);
				desc_chain = NULL;
			}
#ifdef DIAG_SECURITY_FUNC
			else {
				LOG_DIAG
				    ("Creation of sah_Key_Link failed due to bad key"
				     " flag!\n");
			}
#endif				/*DIAG_SECURITY_FUNC */

			/* Check computed ICV against value in Black Key */
			if (ret == FSL_RETURN_OK_S) {
				for (i = 0; i < ICV_LENGTH; i++) {
					if (black_key[ICV_OFFSET + i] !=
					    hmac[i]) {
						ret = FSL_RETURN_AUTH_FAILED_S;
						break;
					}
				}
			}

			/* This is no longer needed. */
			mu->mu_free(mu->mu_ref, hmac);

			/* Compute KEK = SHA1(T | ownerid).  Rewrite slot with value */
			if (ret == FSL_RETURN_OK_S) {
				sah_Link *link1 = NULL;
				sah_Link *link2 = NULL;
				uint32_t header;

				header = (SAH_HDR_MDHA_SET_MODE_HASH	/* #8 */
					  ^ insert_mdha_init
					  ^ insert_mdha_algorithm_sha1
					  ^ insert_mdha_pdata);

				/* Input - Start with T */
				ret =
				    sah_Create_Key_Link(user_ctx->mem_util,
							&link1, &t_key_info);

				if (ret == FSL_RETURN_OK_S) {
					/* Still input - append ownerid */
					ret =
					    sah_Append_Link(user_ctx->mem_util,
							    link1,
							    (void *)&key_info->
							    userid,
							    sizeof(key_info->
								   userid),
							    SAH_USES_LINK_DATA);
				}

				if (ret == FSL_RETURN_OK_S) {
					/* Output - KEK goes into RED slot */
					ret =
					    sah_Create_Key_Link(user_ctx->
								mem_util,
								&link2,
								&t_key_info);
				}

				if (ret == FSL_RETURN_OK_S) {
					/* Put the Hash calculation into the chain. */
					ret =
					    sah_Append_Desc(user_ctx->mem_util,
							    &desc_chain, header,
							    link1, link2);
				}
			}

			/* Compute KEY = AES-decrypt(KEK, KEY') */
			if (ret == FSL_RETURN_OK_S) {
				uint32_t header;
				unsigned rounded_key_length;
				unsigned original_key_length =
				    key_info->key_length;

				header = (SAH_HDR_SKHA_SET_MODE_IV_KEY	/* #1 */
					  ^ insert_skha_mode_ctr
					  ^ insert_skha_algorithm_aes
					  ^ insert_skha_modulus_128);
				/* Load KEK in as the key to use */
				ret =
				    add_in_key_desc(header, NULL, 0,
						    &t_key_info,
						    user_ctx->mem_util,
						    &desc_chain);

				/* Make sure that KEY = AES(KEK, KEY') step writes a multiple
				   of words into the SCC to avoid 'Byte Access errors.' */
				if ((original_key_length & 3) != 0) {
					rounded_key_length =
					    original_key_length + 4 -
					    (original_key_length & 3);
				} else {
					rounded_key_length =
					    original_key_length;
				}

				key_info->key_length = rounded_key_length;
				if (ret == FSL_RETURN_OK_S) {
					/* Now set up for computation.  Result in RED */
					header = SAH_HDR_SKHA_ENC_DEC;	/* #4 */

					ret =
					    add_in_key_desc(header,
							    black_key +
							    KEY_PRIME_OFFSET,
							    rounded_key_length,
							    key_info,
							    user_ctx->mem_util,
							    &desc_chain);
					key_info->key_length =
					    original_key_length;
					/* Perform the operation */
					if (ret == FSL_RETURN_OK_S) {
						ret =
						    sah_Descriptor_Chain_Execute
						    (desc_chain, user_ctx);
					}
				}
			}

			/* Erase tracks */
			t_key_info.userid = 0xdeadbeef;
			t_key_info.handle = 0xdeadbeef;
		}
	}

	return ret;
}				/* unwrap */
示例#4
0
/*!
 * Create and run the chain for a symmetric-key operation.
 *
 * @param user_ctx    Who the user is
 * @param key_info    What key is to be used
 * @param sym_ctx     Info details about algorithm
 * @param encrypt     0 = decrypt, non-zero = encrypt
 * @param length      Number of octets at @a in and @a out
 * @param in          Pointer to input data
 * @param out         Location to store output data
 *
 * @return         The status of handing chain to driver,
 *                 or an earlier argument/flag or allocation
 *                 error.
 */
static fsl_shw_return_t do_symmetric(fsl_shw_uco_t * user_ctx,
				     fsl_shw_sko_t * key_info,
				     fsl_shw_scco_t * sym_ctx,
				     cipher_direction_t encrypt,
				     uint32_t length,
				     const uint8_t * in, uint8_t * out)
{
	fsl_shw_return_t status = FSL_RETURN_ERROR_S;
	uint32_t header;
	sah_Head_Desc *desc_chain = NULL;
	sah_Oct_Str ptr1;

	/* Two different sets of chains, depending on algorithm */
	if (key_info->algorithm == FSL_KEY_ALG_ARC4) {
		if (sym_ctx->flags & FSL_SYM_CTX_INIT) {
			/* Desc. #35 w/ARC4 - start from key */
			header = SAH_HDR_ARC4_SET_MODE_KEY
			    ^ insert_skha_algorithm_arc4;

			status = add_in_key_desc(header, NULL, 0, key_info,
						 user_ctx->mem_util,
						 &desc_chain);

		} else {	/* load SBox */
			/* Desc. #33 w/ARC4 and NO PERMUTE */
			header = SAH_HDR_ARC4_SET_MODE_SBOX
			    ^ insert_skha_no_permute
			    ^ insert_skha_algorithm_arc4;
			status = add_two_in_desc(header, sym_ctx->context, 256,
						 sym_ctx->context + 256, 3,
						 user_ctx->mem_util,
						 &desc_chain);

		}		/* load SBox */

		/* Add in-out data descriptor */
		if ((status == FSL_RETURN_OK_S) && (length != 0)) {
			status = add_in_out_desc(SAH_HDR_SKHA_ENC_DEC,
						 in, length, out, length,
						 user_ctx->mem_util,
						 &desc_chain);
		}

		/* Operation is done ... save what came out? */
		if (sym_ctx->flags & FSL_SYM_CTX_SAVE) {
			/* Desc. #34 - Read SBox, pointers */
			header = SAH_HDR_ARC4_READ_SBOX;
			if (status == FSL_RETURN_OK_S) {
				status =
				    add_two_out_desc(header, sym_ctx->context,
						     256,
						     sym_ctx->context + 256, 3,
						     user_ctx->mem_util,
						     &desc_chain);
			}
		}
	} else {		/* not ARC4 */
		/* Doing 1- or 2- descriptor chain. */
		/* Desc. #1 and algorithm and mode */
		header = SAH_HDR_SKHA_SET_MODE_IV_KEY
		    ^ insert_skha_mode[sym_ctx->mode]
		    ^ insert_skha_algorithm[key_info->algorithm];

		/* Honor 'no key parity checking' for DES and TDES */
		if ((key_info->flags & FSL_SKO_KEY_IGNORE_PARITY) &&
		    ((key_info->algorithm == FSL_KEY_ALG_DES) ||
		     (key_info->algorithm == FSL_KEY_ALG_TDES))) {
			header ^= insert_skha_no_key_parity;
		}

		/* Header by default is decrypting, so... */
		if (encrypt == SYM_ENCRYPT) {
			header ^= insert_skha_encrypt;
		}

		if (sym_ctx->mode == FSL_SYM_MODE_CTR) {
			header ^= insert_skha_modulus[sym_ctx->modulus_exp];
		}

		if ((sym_ctx->mode == FSL_SYM_MODE_ECB)
		    || (sym_ctx->flags & FSL_SYM_CTX_INIT)) {
			ptr1 = block_zeros;
		} else {
			ptr1 = sym_ctx->context;
		}

		status =
		    add_in_key_desc(header, ptr1, sym_ctx->block_size_bytes,
				    key_info, user_ctx->mem_util, &desc_chain);

		/* Add in-out data descriptor */
		if ((length != 0) && (status == FSL_RETURN_OK_S)) {
			status =
			    add_in_out_desc(SAH_HDR_SKHA_ENC_DEC, in, length,
					    out, length, user_ctx->mem_util,
					    &desc_chain);
		}

		/* Unload any desired context */
		if ((sym_ctx->flags & FSL_SYM_CTX_SAVE) &&
		    (status == FSL_RETURN_OK_S)) {
			status = add_two_out_desc(SAH_HDR_SKHA_READ_CONTEXT_IV,
						  NULL, 0, sym_ctx->context,
						  sym_ctx->block_size_bytes,
						  user_ctx->mem_util,
						  &desc_chain);
		}

	}			/* not ARC4 */

	if (status != FSL_RETURN_OK_S) {
		/* Delete possibly-started chain */
		sah_Descriptor_Chain_Destroy(user_ctx->mem_util, &desc_chain);
	} else {
		status = sah_Descriptor_Chain_Execute(desc_chain, user_ctx);
	}

	return status;
}
示例#5
0
/*!
 * Get the precompute information
 *
 *
 * @param   user_ctx
 * @param   key_info
 * @param   hmac_ctx
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_hmac_precompute(
                                fsl_shw_uco_t* user_ctx,
                                fsl_shw_sko_t* key_info,
                                fsl_shw_hmco_t* hmac_ctx)
{
    fsl_shw_return_t status;
    sah_Head_Desc* desc_chain = NULL;
    uint32_t header;


    /* perform sanity check on uco */
    status = sah_validate_uco(user_ctx);
    if (status != FSL_RETURN_OK_S) {
        return status;
    }

    if ((key_info->algorithm != FSL_KEY_ALG_HMAC) ||
        (key_info->key_length > 64)) {
        return FSL_RETURN_BAD_ALGORITHM_S;
    } else if (key_info->key_length == 0) {
        return FSL_RETURN_BAD_KEY_LENGTH_S;
    }

    /* Set up to start the Inner Calculation */
    /* Desc. #8 w/IPAD, & INIT */
    header = SAH_HDR_MDHA_SET_MODE_HASH
             ^ insert_mdha_ipad
             ^ insert_mdha_init
             ^ insert_mdha_algorithm[hmac_ctx->algorithm];

    status = add_key_out_desc(header, key_info,
                             (uint8_t*)hmac_ctx->inner_precompute,
                             hmac_ctx->context_register_length,
                             user_ctx->mem_util, &desc_chain);


   /* Set up for starting Outer calculation */
    if (status == FSL_RETURN_OK_S) {
        /* exchange IPAD bit for OPAD bit */
        header ^= (insert_mdha_ipad ^ insert_mdha_opad);

        /* Theoretically, we can leave this link out and use the key which is
         * already in the register... however, if we do, the resulting opad
         * hash does not have the correct value when using the model. */
        status = add_key_out_desc(header, key_info,
                                 (uint8_t*)hmac_ctx->outer_precompute,
                                 hmac_ctx->context_register_length,
                                 user_ctx->mem_util, &desc_chain);
    }

    /* Pass the chain to the driver. */
    if (status == FSL_RETURN_OK_S) {
        status = sah_Descriptor_Chain_Execute(desc_chain, user_ctx);
        if (status == FSL_RETURN_OK_S) {
            /* flag that precomputes have been entered in this hco
             * assume it'll first be used for initilizing */
            hmac_ctx->flags |= (FSL_HMAC_FLAGS_INIT |
                                FSL_HMAC_FLAGS_PRECOMPUTES_PRESENT);
        }
    } else {
        sah_Descriptor_Chain_Destroy(user_ctx->mem_util, &desc_chain);
    }

    return status;
}
示例#6
0
/*!
 * Get the hmac
 *
 *
 * @param         user_ctx    Info for acquiring memory
 * @param         key_info
 * @param         hmac_ctx
 * @param         msg
 * @param         length
 * @param         result
 * @param         result_len
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_hmac(
                                fsl_shw_uco_t* user_ctx,
                                fsl_shw_sko_t* key_info,
                                fsl_shw_hmco_t* hmac_ctx,
                                const uint8_t* msg,
                                uint32_t length,
                                uint8_t* result,
                                uint32_t result_len)
{
    fsl_shw_return_t ret;
    sah_Head_Desc* desc_chain = NULL;
    uint32_t header;


    /* perform sanity check on uco */
    ret = sah_validate_uco(user_ctx);

    /* check flag consistency */
    /* Note that Final, Init, and Save are an illegal combination when a key
     * is being used. Because of the logic flow of this routine, that is
     * taken care of without being explict */
    if (ret == FSL_RETURN_OK_S) {
        if (
            /* nothing to work on */
            (((hmac_ctx->flags & FSL_HMAC_FLAGS_INIT) == 0) &&
             ((hmac_ctx->flags & FSL_HMAC_FLAGS_LOAD) == 0))        ||
            /* can't do both */
            ((hmac_ctx->flags & FSL_HMAC_FLAGS_INIT) &&
             (hmac_ctx->flags & FSL_HMAC_FLAGS_LOAD))               ||
            /* must be some output */
            (((hmac_ctx->flags & FSL_HMAC_FLAGS_SAVE)     == 0) &&
             ((hmac_ctx->flags & FSL_HMAC_FLAGS_FINALIZE) == 0)))   {
            ret = FSL_RETURN_BAD_FLAG_S;
        }
    }

    /* build descriptor #6 */
    if (ret == FSL_RETURN_OK_S) {

        /* start building descriptor header */
        header = SAH_HDR_MDHA_SET_MODE_MD_KEY ^
                 insert_mdha_algorithm[hmac_ctx->algorithm] ^
                 insert_mdha_init;

        /* if this is to finalize the digest, mark to pad last block */
        if (hmac_ctx->flags & FSL_HMAC_FLAGS_FINALIZE) {
            header ^= insert_mdha_pdata;
        }

        /*** Check if this is a one shot ***/
        if ((hmac_ctx->flags & FSL_HMAC_FLAGS_INIT) &&
            (hmac_ctx->flags & FSL_HMAC_FLAGS_FINALIZE)) {

            header ^= insert_mdha_hmac;

            /*** See if this uses Precomputes ***/
            if (hmac_ctx->flags & FSL_HMAC_FLAGS_PRECOMPUTES_PRESENT) {
                ret = add_two_in_desc(header,
                                      (uint8_t *)hmac_ctx->inner_precompute,
                                      hmac_ctx->context_register_length,
                                      (uint8_t *)hmac_ctx->outer_precompute,
                                      hmac_ctx->context_length,
                                      user_ctx->mem_util,
                                      &desc_chain);
            } else { /*** Precomputes not requested, try using Key ***/
                if (key_info->key != NULL) {
                    /* first, validate the key fields and related flag */
                    if (key_info->key_length == 0) {
                        ret = FSL_RETURN_BAD_KEY_LENGTH_S;
                    } else {
                        if ((key_info->algorithm != FSL_KEY_ALG_HMAC) ||
                            (key_info->key_length > 64)) {
                            ret = FSL_RETURN_BAD_ALGORITHM_S;
                        }
                    }

                    if (ret == FSL_RETURN_OK_S) {
                        /* finish building descriptor header (Key specific) */
                        header ^= insert_mdha_mac_full;
                        ret = add_in_key_desc(header, NULL, 0, key_info,
                                              user_ctx->mem_util, &desc_chain);
                    }
                } else { /*** not using Key or Precomputes, so die ***/
                    ret = FSL_RETURN_BAD_FLAG_S;
                }
            }
        } else {  /*** it's not a one shot, must be multi-step ***/
            /* this the last chunk? */
            if (hmac_ctx->flags & FSL_HMAC_FLAGS_FINALIZE) {
                header ^= insert_mdha_hmac;
                ret = add_two_in_desc(header,
                                      (uint8_t *)hmac_ctx->ongoing_context,
                                      hmac_ctx->context_register_length,
                                      (uint8_t *)hmac_ctx->outer_precompute,
                                      hmac_ctx->context_length,
                                      user_ctx->mem_util, &desc_chain);
            } else { /* not last chunk */
                uint8_t *ptr1;

                if (hmac_ctx->flags & FSL_HMAC_FLAGS_INIT) {
                    /* must be using precomputes, cannot 'chunk' message
                     * starting with a key */
                    if (hmac_ctx->flags & FSL_HMAC_FLAGS_PRECOMPUTES_PRESENT) {
                        ptr1 = (uint8_t *)hmac_ctx->inner_precompute;
                    } else {
                        ret = FSL_RETURN_NO_RESOURCE_S;
                    }
                } else {
                    ptr1 = (uint8_t *)hmac_ctx->ongoing_context;
                }

                if (ret == FSL_RETURN_OK_S) {
                    ret = add_two_in_desc(header, ptr1,
                                        hmac_ctx->context_register_length,
                                        NULL, 0, user_ctx->mem_util,
                                        &desc_chain);
                }
            }
        }
    }  /* end of building descriptor #6 */

    /*** build descriptor #10 & maybe 11 ***/
    if (ret == FSL_RETURN_OK_S) {
        header = SAH_HDR_MDHA_HASH;

        if (hmac_ctx->flags & FSL_HMAC_FLAGS_FINALIZE) {
            /* check that the results parameters seem reasonable */
            if ((result_len != 0) && (result != NULL)) {
                if (result_len > hmac_ctx->context_register_length) {
                    result_len = hmac_ctx->context_register_length;
                }

                /* message in / digest out (descriptor #10) */
                ret = add_in_out_desc(header, msg, length, result, result_len,
                                      user_ctx->mem_util, &desc_chain);

                /*** see if descriptor #11 needs to be built ***/
                if ((hmac_ctx->flags & FSL_HMAC_FLAGS_SAVE) &&
                    (ret == FSL_RETURN_OK_S)) {
                    header = SAH_HDR_MDHA_STORE_DIGEST;
                    /* nothing in / context out */
                    ret = add_two_in_desc(header, NULL, 0,
                                    (uint8_t *)hmac_ctx->ongoing_context,
                                    hmac_ctx->context_register_length,
                                    user_ctx->mem_util, &desc_chain);
                }
            } else {
                /* something wrong with result or its length */
                ret = FSL_RETURN_BAD_DATA_LENGTH_S;
            }
        } else {  /* finalize not set, so store in ongoing context field */
            if ((length % 64) == 0) {
                /* message in / context out */
                ret = add_in_out_desc(header, msg, length,
                                (uint8_t *)hmac_ctx->ongoing_context,
                                hmac_ctx->context_register_length,
                                user_ctx->mem_util, &desc_chain);
            } else {
                ret = FSL_RETURN_BAD_DATA_LENGTH_S;
            }
        }
    }

    /* Pass the chain to the driver. */
    if (ret == FSL_RETURN_OK_S) {
        ret = sah_Descriptor_Chain_Execute(desc_chain, user_ctx);
    } else {
        if (desc_chain != NULL) {
            /* ignore the destroy function's return value, the destroy
             * function's return value is not what went wroung with this
             * routine */
            sah_Descriptor_Chain_Destroy(user_ctx->mem_util, &desc_chain);
        }
    }

    return ret;
}