Beispiel #1
0
/**
  Process an entire GCM packet in one call.
  @param cipher            Index of cipher to use
  @param key               The secret key
  @param keylen            The length of the secret key
  @param IV                The initial vector 
  @param IVlen             The length of the initial vector
  @param adata             The additional authentication data (header)
  @param adatalen          The length of the adata
  @param pt                The plaintext
  @param ptlen             The length of the plaintext (ciphertext length is the same)
  @param ct                The ciphertext
  @param tag               [out] The MAC tag
  @param taglen            [in/out] The MAC tag length
  @param direction         Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
  @return CRYPT_OK on success
 */
int gcm_memory(      int           cipher,
               const unsigned char *key,    unsigned long keylen,
               const unsigned char *IV,     unsigned long IVlen,
               const unsigned char *adata,  unsigned long adatalen,
                     unsigned char *pt,     unsigned long ptlen,
                     unsigned char *ct, 
                     unsigned char *tag,    unsigned long *taglen,
                               int direction)
{
    void      *orig;
    gcm_state *gcm;
    int        err;

    if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
       return err;
    }
 
    if (cipher_descriptor[cipher].accel_gcm_memory != NULL) {
       return 
         cipher_descriptor[cipher].accel_gcm_memory
                                          (key,   keylen,
                                           IV,    IVlen,
                                           adata, adatalen,
                                           pt,    ptlen,
                                           ct,
                                           tag,   taglen,
                                           direction);
    }



#ifndef LTC_GCM_TABLES_SSE2
    orig = gcm = XMALLOC(sizeof(*gcm));
#else
    orig = gcm = XMALLOC(sizeof(*gcm) + 16);
#endif
    if (gcm == NULL) {
        return CRYPT_MEM;
    }

   /* Force GCM to be on a multiple of 16 so we can use 128-bit aligned operations
    * note that we only modify gcm and keep orig intact.  This code is not portable
    * but again it's only for SSE2 anyways, so who cares?
    */
#ifdef LTC_GCM_TABLES_SSE2
   if ((unsigned long)gcm & 15) {
      gcm = (gcm_state *)((unsigned long)gcm + (16 - ((unsigned long)gcm & 15)));
   }
#endif

    if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) {
       goto LTC_ERR;
    }
    if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) {
       goto LTC_ERR;
    }
    if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) {
       goto LTC_ERR;
    }
    if ((err = gcm_process(gcm, pt, ptlen, ct, direction)) != CRYPT_OK) {
       goto LTC_ERR;
    }
    err = gcm_done(gcm, tag, taglen);
LTC_ERR:
    XFREE(orig);
    return err;
}
Beispiel #2
0
TEE_Result tee_authenc_init(
	void *ctx, uint32_t algo, TEE_OperationMode mode, const uint8_t *key,
	size_t key_len, const uint8_t *nonce,
	size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len)
{
	TEE_Result res;
	int ltc_res;
	int ltc_cipherindex;
	unsigned char *payload, *res_payload;
	struct tee_ccm_state *ccm;
	struct tee_gcm_state *gcm;

	res = tee_algo_to_ltc_cipherindex(algo, &ltc_cipherindex);
	if (res != TEE_SUCCESS)
		return TEE_ERROR_NOT_SUPPORTED;
	switch (algo) {
	case TEE_ALG_AES_CCM:
		/* Check the key length */
		if ((!key) || (key_len > TEE_CCM_KEY_MAX_LENGTH))
			return TEE_ERROR_BAD_PARAMETERS;

		/* check the nonce */
		if (nonce_len > TEE_CCM_NONCE_MAX_LENGTH)
			return TEE_ERROR_BAD_PARAMETERS;

		/* check the tag len */
		if ((tag_len < 4) ||
		    (tag_len > TEE_CCM_TAG_MAX_LENGTH) ||
		    (tag_len % 2 != 0))
			return TEE_ERROR_NOT_SUPPORTED;

		/* allocate payload */
		payload = malloc(payload_len + TEE_CCM_KEY_MAX_LENGTH);
		if (!payload)
			return TEE_ERROR_OUT_OF_MEMORY;
		res_payload = malloc(payload_len + TEE_CCM_KEY_MAX_LENGTH);
		if (!res_payload) {
			free(payload);
			return TEE_ERROR_OUT_OF_MEMORY;
		}

		/* initialize the structure */
		ccm = ctx;
		memset(ccm, 0, sizeof(struct tee_ccm_state));
		memcpy(ccm->key, key, key_len);
		ccm->key_len = key_len;			/* the key length */
		if (nonce && nonce_len) {
			memcpy(ccm->nonce, nonce, nonce_len);
			ccm->nonce_len = nonce_len;
		} else {
			ccm->nonce_len = 0;
		}
		ccm->tag_len = tag_len;
		ccm->aad_len = aad_len;
		ccm->payload_len = payload_len;
		ccm->payload = payload;
		ccm->res_payload = res_payload;
		ccm->ltc_cipherindex = ltc_cipherindex;

		if (ccm->aad_len) {
			ccm->header = malloc(ccm->aad_len);
			if (!ccm->header) {
				free(payload);
				free(res_payload);
				return TEE_ERROR_OUT_OF_MEMORY;
			}
		}

		/* memset the payload to 0 that will be used for padding */
		memset(ccm->payload, 0, payload_len + TEE_CCM_KEY_MAX_LENGTH);
		break;

	case TEE_ALG_AES_GCM:
		/* reset the state */
		gcm = ctx;
		memset(gcm, 0, sizeof(struct tee_gcm_state));
		gcm->tag_len = tag_len;

		ltc_res = gcm_init(
			&gcm->ctx, ltc_cipherindex, key, key_len);
		if (ltc_res != CRYPT_OK)
			return TEE_ERROR_BAD_STATE;

		/* Add the IV */
		ltc_res = gcm_add_iv(&gcm->ctx, nonce, nonce_len);
		if (ltc_res != CRYPT_OK)
			return TEE_ERROR_BAD_STATE;
		break;

	default:
		return TEE_ERROR_NOT_SUPPORTED;
	}

	return TEE_SUCCESS;
}