Beispiel #1
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 */
Beispiel #2
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;
}
/*!
 * 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;
}