xref: /optee_os/core/drivers/crypto/crypto_api/cipher/cipher.c (revision e7b17391c7cce3e930648a72c8742cb169316de0)
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