1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2018-2020 NXP
4 *
5 * Crypto Cipher interface implementation to enable HW driver.
6 */
7 #include <assert.h>
8 #include <crypto/crypto.h>
9 #include <crypto/crypto_impl.h>
10 #include <drvcrypt.h>
11 #include <drvcrypt_cipher.h>
12 #include <kernel/panic.h>
13 #include <malloc.h>
14 #include <utee_defines.h>
15 #include <util.h>
16
17 static const struct crypto_cipher_ops cipher_ops;
18
19 /*
20 * Returns the reference to the driver context
21 *
22 * @ctx Reference the API context pointer
23 */
to_cipher_ctx(struct crypto_cipher_ctx * ctx)24 static struct crypto_cipher *to_cipher_ctx(struct crypto_cipher_ctx *ctx)
25 {
26 assert(ctx && ctx->ops == &cipher_ops);
27
28 return container_of(ctx, struct crypto_cipher, cipher_ctx);
29 }
30
31 /*
32 * Free cipher context
33 *
34 * @ctx Reference the API context pointer
35 */
cipher_free_ctx(struct crypto_cipher_ctx * ctx)36 static void cipher_free_ctx(struct crypto_cipher_ctx *ctx)
37 {
38 struct crypto_cipher *cipher = to_cipher_ctx(ctx);
39
40 if (cipher->op && cipher->op->free_ctx)
41 cipher->op->free_ctx(cipher->ctx);
42
43 free(cipher);
44 }
45
46 /*
47 * Copy cipher context
48 *
49 * @dst_ctx [out] Reference the API context pointer destination
50 * @src_ctx Reference the API context pointer source
51 */
cipher_copy_state(struct crypto_cipher_ctx * dst_ctx,struct crypto_cipher_ctx * src_ctx)52 static void cipher_copy_state(struct crypto_cipher_ctx *dst_ctx,
53 struct crypto_cipher_ctx *src_ctx)
54 {
55 struct crypto_cipher *cipher_src = to_cipher_ctx(src_ctx);
56 struct crypto_cipher *cipher_dst = to_cipher_ctx(dst_ctx);
57
58 if (cipher_src->op && cipher_src->op->copy_state)
59 cipher_src->op->copy_state(cipher_dst->ctx, cipher_src->ctx);
60 }
61
62 /*
63 * Initialization of the cipher operation
64 *
65 * @ctx Reference the API context pointer
66 * @mode Operation mode
67 * @key1 First Key
68 * @key1_len Length of the first key
69 * @key2 Second Key
70 * @key2_len Length of the second key
71 * @iv Initial Vector
72 * @iv_len Length of the IV
73 */
cipher_init(struct crypto_cipher_ctx * ctx,TEE_OperationMode mode,const uint8_t * key1,size_t key1_len,const uint8_t * key2,size_t key2_len,const uint8_t * iv,size_t iv_len)74 static TEE_Result cipher_init(struct crypto_cipher_ctx *ctx,
75 TEE_OperationMode mode, const uint8_t *key1,
76 size_t key1_len, const uint8_t *key2,
77 size_t key2_len, const uint8_t *iv, size_t iv_len)
78 {
79 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
80 struct crypto_cipher *cipher = to_cipher_ctx(ctx);
81
82 if ((!key1 && key1_len) || (!key2 && key2_len) || (!iv && iv_len)) {
83 CRYPTO_TRACE("One of the key is not correct");
84 CRYPTO_TRACE("key1 @%p-%zu bytes", key1, key1_len);
85 CRYPTO_TRACE("key2 @%p-%zu bytes", key1, key1_len);
86 CRYPTO_TRACE("iv @%p-%zu bytes", iv, iv_len);
87 return TEE_ERROR_BAD_PARAMETERS;
88 }
89
90 if (cipher->op && cipher->op->init) {
91 struct drvcrypt_cipher_init dinit = {
92 .ctx = cipher->ctx,
93 .encrypt = (mode == TEE_MODE_ENCRYPT),
94 .key1.data = (uint8_t *)key1,
95 .key1.length = key1_len,
96 .key2.data = (uint8_t *)key2,
97 .key2.length = key2_len,
98 .iv.data = (uint8_t *)iv,
99 .iv.length = iv_len,
100 };
101
102 ret = cipher->op->init(&dinit);
103 }
104
105 CRYPTO_TRACE("cipher ret 0x%" PRIX32, ret);
106 return ret;
107 }
108
109 /*
110 * Update of the cipher operation
111 *
112 * @ctx Reference the API context pointer
113 * @last_block True if last block to handle
114 * @data Data to encrypt/decrypt
115 * @len Length of the input data and output result
116 * @dst [out] Output data of the operation
117 */
cipher_update(struct crypto_cipher_ctx * ctx,bool last_block,const uint8_t * data,size_t len,uint8_t * dst)118 static TEE_Result cipher_update(struct crypto_cipher_ctx *ctx, bool last_block,
119 const uint8_t *data, size_t len, uint8_t *dst)
120 {
121 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
122 struct crypto_cipher *cipher = to_cipher_ctx(ctx);
123
124 if (!dst) {
125 CRYPTO_TRACE("Destination buffer error");
126 return TEE_ERROR_BAD_PARAMETERS;
127 }
128
129 if (!data && len) {
130 CRYPTO_TRACE("Bad data data @%p-%zu bytes", data, len);
131 return TEE_ERROR_BAD_PARAMETERS;
132 }
133
134 if (cipher->op && cipher->op->update) {
135 struct drvcrypt_cipher_update dupdate = {
136 .ctx = cipher->ctx,
137 .last = last_block,
138 .src.data = (uint8_t *)data,
139 .src.length = len,
140 .dst.data = dst,
141 .dst.length = len,
142 };
143
144 ret = cipher->op->update(&dupdate);
145 }
146
147 CRYPTO_TRACE("cipher ret 0x%" PRIX32, ret);
148 return ret;
149 }
150
151 /*
152 * Finalize the cipher operation
153 *
154 * @ctx Reference the API context pointer
155 */
cipher_final(struct crypto_cipher_ctx * ctx)156 static void cipher_final(struct crypto_cipher_ctx *ctx)
157 {
158 struct crypto_cipher *cipher = to_cipher_ctx(ctx);
159
160 if (cipher->op && cipher->op->final)
161 cipher->op->final(cipher->ctx);
162 }
163
164 static const struct crypto_cipher_ops cipher_ops = {
165 .init = cipher_init,
166 .update = cipher_update,
167 .final = cipher_final,
168 .free_ctx = cipher_free_ctx,
169 .copy_state = cipher_copy_state,
170 };
171
drvcrypt_cipher_alloc_ctx(struct crypto_cipher_ctx ** ctx,uint32_t algo)172 TEE_Result drvcrypt_cipher_alloc_ctx(struct crypto_cipher_ctx **ctx,
173 uint32_t algo)
174 {
175 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
176 struct crypto_cipher *cipher = NULL;
177
178 CRYPTO_TRACE("Cipher alloc_ctx algo 0x%" PRIX32, algo);
179
180 assert(ctx);
181
182 cipher = calloc(1, sizeof(*cipher));
183 if (!cipher)
184 return TEE_ERROR_OUT_OF_MEMORY;
185
186 cipher->op = drvcrypt_get_ops(CRYPTO_CIPHER);
187 if (cipher->op && cipher->op->alloc_ctx)
188 ret = cipher->op->alloc_ctx(&cipher->ctx, algo);
189
190 if (ret != TEE_SUCCESS) {
191 free(cipher);
192 } else {
193 cipher->cipher_ctx.ops = &cipher_ops;
194 *ctx = &cipher->cipher_ctx;
195 }
196
197 CRYPTO_TRACE("Cipher alloc_ctx ret 0x%" PRIX32, ret);
198
199 return ret;
200 }
201