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