示例#1
0
static void *my_malloc(void *ref, size_t n)
{
	register void *mem;

#ifndef DIAG_MEM_ERRORS
	mem = os_alloc_memory(n, GFP_KERNEL);

#else
	{
		uint32_t rand;
		/* are we feeling lucky ? */
		os_get_random_bytes(&rand, sizeof(rand));
		if ((rand % DIAG_MEM_CONST) == 0) {
			mem = 0;
		} else {
			mem = os_alloc_memory(n, GFP_ATOMIC);
		}
	}
#endif				/* DIAG_MEM_ERRORS */

#ifdef DIAG_MEM
	sprintf(Diag_msg, "API kmalloc: %p for %d\n", mem, n);
	LOG_KDIAG(Diag_msg);
#endif
	ref = 0;		/* unused param warning */
	return mem;
}
示例#2
0
/*!
 * Get random data.
 *
 * @param      user_ctx  A user context from #fsl_shw_register_user().
 * @param      length    The number of octets of @a data being requested.
 * @param data      A pointer to a location of @a length octets to where
 *                       random data will be returned.
 *
 * @return     FSL_RETURN_NO_RESOURCE_S  A return code of type #fsl_shw_return_t.
 *             FSL_RETURN_OK_S
 */
fsl_shw_return_t fsl_shw_get_random(fsl_shw_uco_t * user_ctx, uint32_t length,
				    uint8_t * data)
{
	fsl_shw_return_t return_code = FSL_RETURN_NO_RESOURCE_S;
	/* Boost up length to cover any 'missing' bytes at end of a word */
	uint32_t *buf = os_alloc_memory(length + 3, 0);
	volatile rng_work_entry_t *work = os_alloc_memory(sizeof(*work), 0);

	if ((rng_availability != RNG_STATUS_OK) || (buf == NULL)
	    || (work == NULL)) {
		if (rng_availability != RNG_STATUS_OK) {
			LOG_KDIAG_ARGS("rng not available: %d\n",
				       rng_availability);
		} else {
			LOG_KDIAG_ARGS
			    ("Resource allocation failure: %d or %d bytes",
			     length, sizeof(*work));
		}
		/* Cannot perform function.  Clean up and clear out. */
		if (buf != NULL) {
			os_free_memory(buf);
		}
		if (work != NULL) {
			os_free_memory((void *)work);
		}
	} else {
		unsigned blocking = user_ctx->flags & FSL_UCO_BLOCKING_MODE;

		work->hdr.user_ctx = user_ctx;
		work->hdr.flags = user_ctx->flags;
		work->hdr.callback = user_ctx->callback;
		work->hdr.user_ref = user_ctx->user_ref;
		work->hdr.postprocess = finish_random;
		work->length = length;
		work->data_local = buf;
		work->data_user = data;

		RNG_ADD_WORK_ENTRY((rng_work_entry_t *) work);

		if (blocking) {
			os_sleep(rng_wait_queue, work->completed != FALSE,
				 FALSE);
			finish_random((shw_queue_entry_t *) work);
			return_code = work->hdr.code;
			os_free_memory((void *)work);
		} else {
			return_code = FSL_RETURN_OK_S;
		}
	}

	return return_code;
}				/* fsl_shw_get_entropy */
示例#3
0
/******************************************************************************
*
* CAUTION:  This function may sleep in low-memory situations, as it uses
*           kmalloc ( ..., GFP_KERNEL).
******************************************************************************/
sah_Queue *sah_Queue_Construct (void)
{
    sah_Queue *q = (sah_Queue *)os_alloc_memory (sizeof(sah_Queue),
                                                    GFP_KERNEL);

    if (q != NULL) {
        /* Initialise the queue to an empty state. */
        q->head = NULL;
        q->tail = NULL;
        q->count = 0;
    }
#ifdef DIAG_DRV_QUEUE
    else {
        LOG_KDIAG ("kmalloc() failed.");
    }
#endif

    return q;
}
示例#4
0
/*!
 * Add entropy to random number generator.
 *
 * @param      user_ctx  A user context from #fsl_shw_register_user().
 * @param      length    Number of bytes at @a data.
 * @param      data      Entropy to add to random number generator.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_add_entropy(fsl_shw_uco_t * user_ctx, uint32_t length,
				     uint8_t * data)
{
	fsl_shw_return_t return_code = FSL_RETURN_NO_RESOURCE_S;
#if defined(FSL_HAVE_RNGC)
	/* No Entropy Register in RNGC */
	return_code = FSL_RETURN_OK_S;
#else
	uint32_t *local_data = NULL;
	if (rng_availability == RNG_STATUS_OK) {
		/* make 32-bit aligned place to hold data */
		local_data = os_alloc_memory(length + 3, 0);
		if (local_data == NULL) {
			return_code = FSL_RETURN_NO_RESOURCE_S;
		} else {
			memcpy(local_data, data, length);

			/* Copy one word at a time to hardware */
			while (TRUE) {
				register uint32_t *ptr = local_data;

				RNG_ADD_ENTROPY(*ptr++);
				if (length <= 4) {
					break;
				}
				length -= 4;
			}
			return_code = FSL_RETURN_OK_S;
			os_free_memory(local_data);
		}		/* else local_data not NULL */

	}
#endif
	/* rng_availability is OK */
	return return_code;
}				/* fsl_shw_add_entropy */
    fsl_shw_return_t shw_kso_init_data(fsl_shw_uco_t *user_ctx,
					void **user_data)
{
	int retval = FSL_RETURN_ERROR_S;
	keystore_data_t *keystore_data = NULL;
	fsl_shw_pco_t *capabilities = fsl_shw_get_capabilities(user_ctx);
	uint32_t partition_size;
	uint32_t slot_count;
	uint32_t keystore_data_size;
	uint8_t UMID[16] = {
	0x42, 0, 0, 0, 0x43, 0, 0, 0, 0x19, 0, 0, 0, 0x59, 0, 0, 0};
	uint32_t permissions =
	    FSL_PERM_TH_R | FSL_PERM_TH_W | FSL_PERM_HD_R | FSL_PERM_HD_W |
	    FSL_PERM_HD_X;

	/* Look up the size of a partition to see how big to make the keystore */
	partition_size = fsl_shw_pco_get_spo_size_bytes(capabilities);

	/* Calculate the required size of the keystore data structure, based on the
	  * number of keys that can fit in the partition.
	  */
	slot_count = partition_size / KEYSTORE_SLOT_SIZE;
	keystore_data_size =
	    sizeof(keystore_data_t) +
	    slot_count * sizeof(keystore_data_slot_info_t);

#ifdef __KERNEL__
	keystore_data = os_alloc_memory(keystore_data_size, GFP_KERNEL);

#else
	keystore_data = malloc(keystore_data_size);

#endif
	if (keystore_data == NULL) {
		retval = FSL_RETURN_NO_RESOURCE_S;
		goto out;
	}

    /* Clear the memory (effectively clear all key assignments) */
    memset(keystore_data, 0, keystore_data_size);

   /* Place the slot information structure directly after the keystore data
   	* structure.
	*/
	    keystore_data->slot =
	    (keystore_data_slot_info_t *) (keystore_data + 1);
	keystore_data->slot_count = slot_count;

	/* Retrieve a secure partition to put the keystore in. */
	keystore_data->base_address =
	    fsl_shw_smalloc(user_ctx, partition_size, UMID, permissions);
	if (keystore_data->base_address == NULL) {
		retval = FSL_RETURN_NO_RESOURCE_S;
		goto out;
	}
	*user_data = keystore_data;
	retval = FSL_RETURN_OK_S;
out:if (retval != FSL_RETURN_OK_S) {
		if (keystore_data != NULL) {
			if (keystore_data->base_address != NULL)
				fsl_shw_sfree(NULL,
					       keystore_data->base_address);

#ifdef __KERNEL__
			    os_free_memory(keystore_data);

#else
			    free(keystore_data);

#endif
		}
	}
	return retval;
}
示例#6
0
/*!
 * Perform wrapping of a black key from a RED slot (or the PK register)
 *
 * @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 = FSL_RETURN_OK_S;
	fsl_shw_sko_t t_key_info;	/* for holding T */
	fsl_shw_scco_t t_key_ctx;
	fsl_shw_sko_t kek_key_info;
	fsl_shw_scco_t kek_ctx;
	unsigned original_key_length = key_info->key_length;
	unsigned rounded_key_length;
	uint8_t T[T_LENGTH];
	uint8_t kek[KEK_LENGTH + 20];
	uint8_t *red_key = 0;
	int red_key_malloced = 0;	/* bool */
	int pk_was_held = 0;	/* bool */
	uint8_t saved_pk[21];
	uint8_t pk_needs_restoration;	/* bool */
	di_return_t di_code;

	ret = check_wrap_key(user_ctx->wrap_key);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	if (black_key == NULL) {
		ret = FSL_RETURN_ERROR_S;
		goto out;
	}

	if (key_info->flags & FSL_SKO_KEY_SELECT_PF_KEY) {
		if ((key_info->pf_key != FSL_SHW_PF_KEY_PRG)
		    && (key_info->pf_key != FSL_SHW_PF_KEY_IIM_PRG)) {
			ret = FSL_RETURN_ERROR_S;
			goto out;
		}
	} else {
		if (!(key_info->flags & FSL_SKO_KEY_ESTABLISHED)) {
			ret = FSL_RETURN_BAD_FLAG_S;	/* not established! */
			goto out;
		}
	}

	black_key[ALGORITHM_OFFSET] = key_info->algorithm;

#ifndef DO_REPEATABLE_WRAP
	/* Compute T = RND() */
	ret = fsl_shw_get_random(user_ctx, T_LENGTH, T);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}
#else
	memcpy(T, T_block, T_LENGTH);
#endif

	/* Compute KEK = SHA256(T | ownerid). */
	ret = calc_kek((uint8_t *) & key_info->userid, sizeof(key_info->userid),
		       T, kek);
	if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("Calculation of KEK failed\n");
#endif				/*DIAG_SECURITY_FUNC */
		goto out;
	}

	rounded_key_length = ROUND_LENGTH(original_key_length);

	di_code = dryice_get_programmed_key(saved_pk, 8 * 21);
	if (di_code != DI_SUCCESS) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG_ARGS("Could not save current PK: %s\n",
			      di_error_string(di_code));
#endif
		ret = FSL_RETURN_ERROR_S;
		goto out;
	}

	/*
	 * Load KEK into DI PKR.  Note that we are NOT permuting it before loading,
	 * so we are using it as though it is a 168-bit key ready for the SCC.
	 */
	di_code = dryice_set_programmed_key(kek, 8 * 21, 0);
	if (di_code == DI_ERR_INUSE) {
		/* Temporarily reprogram the PK out from under the user */
		pk_was_held = 1;
		dryice_release_programmed_key();
		di_code = dryice_set_programmed_key(kek, 8 * 21, 0);
	}
	if (di_code != DI_SUCCESS) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG_ARGS("Could not program KEK: %s\n",
			      di_error_string(di_code));
#endif
		ret = FSL_RETURN_ERROR_S;
		goto out;
	}
	pk_needs_restoration = 1;
	dryice_release_programmed_key();

	/* Find red key */
	if (key_info->flags & FSL_SKO_KEY_SELECT_PF_KEY) {
		black_key[LENGTH_OFFSET] = 21;
		rounded_key_length = 24;

		red_key = saved_pk;
	} else {
		black_key[LENGTH_OFFSET] = key_info->key_length;

		red_key = os_alloc_memory(key_info->key_length, 0);
		if (red_key == NULL) {
			ret = FSL_RETURN_NO_RESOURCE_S;
			goto out;
		}
		red_key_malloced = 1;

		ret = fsl_shw_read_key(user_ctx, key_info, red_key);
		if (ret != FSL_RETURN_OK_S) {
			goto out;
		}
	}

#ifdef DIAG_SECURITY_FUNC
	dump("KEY", red_key, black_key[LENGTH_OFFSET]);
#endif
	/* Compute KEY' = TDES-encrypt(KEK, KEY) */
	fsl_shw_sko_init_pf_key(&kek_key_info, FSL_KEY_ALG_TDES,
				FSL_SHW_PF_KEY_PRG);
	fsl_shw_sko_set_key_length(&kek_key_info, KEK_LENGTH);

	fsl_shw_scco_init(&kek_ctx, FSL_KEY_ALG_TDES, FSL_SYM_MODE_CBC);
	fsl_shw_scco_set_flags(&kek_ctx, FSL_SYM_CTX_LOAD);
	fsl_shw_scco_set_context(&kek_ctx, (uint8_t *) & key_info->userid);
	ret = fsl_shw_symmetric_encrypt(user_ctx, &kek_key_info, &kek_ctx,
					rounded_key_length,
					red_key, black_key + KEY_PRIME_OFFSET);
	if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("Encryption of KEY failed\n");
#endif				/*DIAG_SECURITY_FUNC */
		goto out;
	}

	/* Set up flags info */
	black_key[FLAGS_OFFSET] = 0;
	if (key_info->flags & FSL_SKO_KEY_SW_KEY) {
		black_key[FLAGS_OFFSET] |= FLAGS_SW_KEY;
	}
#ifdef DIAG_SECURITY_FUNC
	dump("KEY'", black_key + KEY_PRIME_OFFSET, rounded_key_length);
#endif
	/* Compute and store ICV into Black Key */
	ret = calc_icv(T,
		       (uint8_t *) & key_info->userid,
		       sizeof(key_info->userid),
		       black_key, original_key_length, black_key + ICV_OFFSET);
	if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("Calculation of ICV failed\n");
#endif				/*DIAG_SECURITY_FUNC */
		goto out;
	}

	/* Compute T' = 3des-enc-ecb(wrap_key, T); Result goes to Black Key */
	init_wrap_key(user_ctx->wrap_key, &t_key_info, &t_key_ctx);
	ret = fsl_shw_symmetric_encrypt(user_ctx, &t_key_info, &t_key_ctx,
					T_LENGTH,
					T, black_key + T_PRIME_OFFSET);
	if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("Encryption of nonce failed");
#endif
		goto out;
	}
#ifdef DIAG_SECURITY_FUNC
	dump("black", black_key, KEY_PRIME_OFFSET + black_key[LENGTH_OFFSET]);
#endif

      out:
	if (pk_needs_restoration) {
		dryice_set_programmed_key(saved_pk, 8 * 21, 0);
	}

	if (!pk_was_held) {
		dryice_release_programmed_key();
	}

	if (red_key_malloced) {
		memset(red_key, 0, key_info->key_length);
		os_free_memory(red_key);
	}

	key_info->key_length = original_key_length;

	/* Erase tracks of confidential data */
	memset(T, 0, T_LENGTH);
	memset(&t_key_info, 0, sizeof(t_key_info));
	memset(&t_key_ctx, 0, sizeof(t_key_ctx));
	memset(&kek_key_info, 0, sizeof(kek_key_info));
	memset(&kek_ctx, 0, sizeof(kek_ctx));
	memset(kek, 0, sizeof(kek));
	memset(saved_pk, 0, sizeof(saved_pk));

	return ret;
}				/* wrap */