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