1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved
4  * Author: Jorge Ramirez <jorge@foundries.io>
5  */
6 
7 #include <assert.h>
8 #include <crypto/crypto_impl.h>
9 #include <se050.h>
10 #include <se050_cipher_algorithms.h>
11 #include <string.h>
12 #include <utee_defines.h>
13 #include <util.h>
14 
15 struct se050_aes_ctr_ctx {
16 	struct crypto_cipher_ctx ctx;
17 	sss_se05x_symmetric_t aes_ctx;
18 	sss_se05x_object_t key_obj;
19 	uint8_t *cnt; /* shared reference counter for duplicated ciphers */
20 	int nc_off;
21 	unsigned char counter[TEE_AES_BLOCK_SIZE];
22 	unsigned char block[TEE_AES_BLOCK_SIZE];
23 };
24 
to_aes_ctr_ctx(struct crypto_cipher_ctx * ctx)25 static struct se050_aes_ctr_ctx *to_aes_ctr_ctx(struct crypto_cipher_ctx *ctx)
26 {
27 	return container_of(ctx, struct se050_aes_ctr_ctx, ctx);
28 }
29 
se050_aes_ctr_init(struct crypto_cipher_ctx * ctx,TEE_OperationMode mode __unused,const uint8_t * key1,size_t key1_len,const uint8_t * key2 __unused,size_t key2_len __unused,const uint8_t * iv,size_t iv_len __unused)30 static TEE_Result se050_aes_ctr_init(struct crypto_cipher_ctx *ctx,
31 				     TEE_OperationMode mode __unused,
32 				     const uint8_t *key1,
33 				     size_t key1_len,
34 				     const uint8_t *key2 __unused,
35 				     size_t key2_len __unused,
36 				     const uint8_t *iv, size_t iv_len __unused)
37 {
38 	struct se050_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx);
39 	sss_status_t st = kStatus_SSS_Success;
40 	uint32_t oid = 0;
41 
42 	if (c->key_obj.keyId)
43 		goto init;
44 
45 	memcpy(c->counter, iv, sizeof(c->counter));
46 
47 	st = sss_se05x_key_object_init(&c->key_obj, se050_kstore);
48 	if (st != kStatus_SSS_Success)
49 		return TEE_ERROR_GENERIC;
50 
51 	st = se050_get_oid(&oid);
52 	if (st != kStatus_SSS_Success)
53 		return TEE_ERROR_GENERIC;
54 
55 	st = sss_se05x_key_object_allocate_handle(&c->key_obj, oid,
56 						  kSSS_KeyPart_Default,
57 						  kSSS_CipherType_AES, 0,
58 						  kKeyObject_Mode_Transient);
59 	if (st != kStatus_SSS_Success)
60 		return TEE_ERROR_GENERIC;
61 
62 	st = sss_se05x_key_store_set_key(se050_kstore, &c->key_obj,
63 					 key1, key1_len, key1_len * 8, NULL, 0);
64 	if (st != kStatus_SSS_Success)
65 		return TEE_ERROR_GENERIC;
66 
67 	st = sss_se05x_symmetric_context_init(&c->aes_ctx, se050_session,
68 					      &c->key_obj,
69 					      kAlgorithm_SSS_AES_ECB,
70 					      kMode_SSS_Encrypt);
71 	if (st != kStatus_SSS_Success)
72 		return TEE_ERROR_GENERIC;
73 init:
74 	st = sss_se05x_cipher_init(&c->aes_ctx, (uint8_t *)NULL, 0);
75 	if (st != kStatus_SSS_Success)
76 		return TEE_ERROR_GENERIC;
77 
78 	return TEE_SUCCESS;
79 }
80 
se050_aes_ctr_update(struct crypto_cipher_ctx * ctx,bool last_block __unused,const uint8_t * data,size_t len,uint8_t * dst)81 static TEE_Result se050_aes_ctr_update(struct crypto_cipher_ctx *ctx,
82 				       bool last_block __unused,
83 				       const uint8_t *data, size_t len,
84 				       uint8_t *dst)
85 {
86 	struct se050_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx);
87 	sss_status_t st = kStatus_SSS_Success;
88 	size_t dst_len = len;
89 	int i = 0;
90 	int n = 0;
91 	int j = 0;
92 
93 	n = c->nc_off;
94 	while (len--) {
95 		dst_len = sizeof(c->counter);
96 		if (n == 0) {
97 			st = sss_se05x_cipher_update(&c->aes_ctx,
98 						     c->counter, 16,
99 						     c->block, &dst_len);
100 			if (st != kStatus_SSS_Success)
101 				return TEE_ERROR_BAD_STATE;
102 
103 			for (i = 16; i > 0; i--)
104 				if (++c->counter[i - 1] != 0)
105 					break;
106 		}
107 		j = *data++;
108 		*dst++ = (unsigned char)(j ^ c->block[n]);
109 		n = (n + 1) & 0x0F;
110 	}
111 
112 	c->nc_off = n;
113 	return TEE_SUCCESS;
114 }
115 
do_final(struct crypto_cipher_ctx * ctx)116 static void do_final(struct crypto_cipher_ctx *ctx)
117 {
118 	struct se050_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx);
119 
120 	if (!se050_refcount_final_ctx(c->cnt)) {
121 		memset(c->block, 0, sizeof(c->block));
122 		return;
123 	}
124 
125 	if (c->key_obj.keyId)
126 		sss_se05x_key_store_erase_key(se050_kstore, &c->key_obj);
127 
128 	sss_se05x_symmetric_context_free(&c->aes_ctx);
129 }
130 
do_free(struct crypto_cipher_ctx * ctx)131 static void do_free(struct crypto_cipher_ctx *ctx)
132 {
133 	free(to_aes_ctr_ctx(ctx));
134 }
135 
do_copy_state(struct crypto_cipher_ctx * dst_ctx,struct crypto_cipher_ctx * src_ctx)136 static void do_copy_state(struct crypto_cipher_ctx *dst_ctx,
137 			  struct crypto_cipher_ctx *src_ctx)
138 {
139 	struct se050_aes_ctr_ctx *src = to_aes_ctr_ctx(src_ctx);
140 	struct se050_aes_ctr_ctx *dst = to_aes_ctr_ctx(dst_ctx);
141 
142 	se050_refcount_init_ctx(&src->cnt);
143 	memcpy(dst, src, sizeof(*dst));
144 }
145 
146 static struct crypto_cipher_ops aes_ctr_ops = {
147 	.update = se050_aes_ctr_update,
148 	.copy_state = do_copy_state,
149 	.init = se050_aes_ctr_init,
150 	.free_ctx = do_free,
151 	.final = do_final,
152 };
153 
se050_aes_ctr_allocate(void ** ctx)154 TEE_Result se050_aes_ctr_allocate(void **ctx)
155 {
156 	struct se050_aes_ctr_ctx *c = NULL;
157 
158 	c = calloc(1, sizeof(*c));
159 	if (!c)
160 		return TEE_ERROR_OUT_OF_MEMORY;
161 
162 	c->ctx.ops = &aes_ctr_ops;
163 	*ctx = &c->ctx;
164 
165 	return TEE_SUCCESS;
166 }
167