1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2014 Freescale Semiconductor, Inc.
4 *
5 */
6
7#include <common.h>
8#include <cpu_func.h>
9#include <log.h>
10#include <malloc.h>
11#include <memalign.h>
12#include <fsl_sec.h>
13#include <asm/cache.h>
14#include <linux/errno.h>
15#include "jobdesc.h"
16#include "desc.h"
17#include "jr.h"
18
19/**
20 * blob_decap() - Decapsulate the data from a blob
21 * @key_mod:    - Key modifier address
22 * @src:        - Source address (blob)
23 * @dst:        - Destination address (data)
24 * @len:        - Size of decapsulated data
25 *
26 * Note: Start and end of the key_mod, src and dst buffers have to be aligned to
27 * the cache line size (ARCH_DMA_MINALIGN) for the CAAM operation to succeed.
28 *
29 * Returns zero on success, negative on error.
30 */
31int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len)
32{
33	int ret, size, i = 0;
34	u32 *desc;
35
36	if (!IS_ALIGNED((uintptr_t)key_mod, ARCH_DMA_MINALIGN) ||
37	    !IS_ALIGNED((uintptr_t)src, ARCH_DMA_MINALIGN) ||
38	    !IS_ALIGNED((uintptr_t)dst, ARCH_DMA_MINALIGN)) {
39		puts("Error: blob_decap: Address arguments are not aligned!\n");
40		return -EINVAL;
41	}
42
43	printf("\nDecapsulating blob to get data\n");
44	desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE);
45	if (!desc) {
46		debug("Not enough memory for descriptor allocation\n");
47		return -ENOMEM;
48	}
49
50	size = ALIGN(16, ARCH_DMA_MINALIGN);
51	flush_dcache_range((unsigned long)key_mod,
52			   (unsigned long)key_mod + size);
53
54	size = ALIGN(BLOB_SIZE(len), ARCH_DMA_MINALIGN);
55	flush_dcache_range((unsigned long)src,
56			   (unsigned long)src + size);
57
58	inline_cnstr_jobdesc_blob_decap(desc, key_mod, src, dst, len);
59
60	debug("Descriptor dump:\n");
61	for (i = 0; i < 14; i++)
62		debug("Word[%d]: %08x\n", i, *(desc + i));
63
64	size = ALIGN(sizeof(int) * MAX_CAAM_DESCSIZE, ARCH_DMA_MINALIGN);
65	flush_dcache_range((unsigned long)desc,
66			   (unsigned long)desc + size);
67
68	flush_dcache_range((unsigned long)dst,
69			   (unsigned long)dst + size);
70
71	ret = run_descriptor_jr(desc);
72
73	if (ret) {
74		/* clear the blob data output buffer */
75		memset(dst, 0x00, len);
76		size = ALIGN(len, ARCH_DMA_MINALIGN);
77		flush_dcache_range((unsigned long)dst, (unsigned long)dst + size);
78		printf("Error in blob decapsulation: %d\n", ret);
79	} else {
80		size = ALIGN(len, ARCH_DMA_MINALIGN);
81		invalidate_dcache_range((unsigned long)dst,
82					(unsigned long)dst + size);
83
84		puts("Blob decapsulation successful.\n");
85	}
86
87	free(desc);
88	return ret;
89}
90
91/**
92 * blob_encap() - Encapsulate the data as a blob
93 * @key_mod:    - Key modifier address
94 * @src:        - Source address (data)
95 * @dst:        - Destination address (blob)
96 * @len:        - Size of data to be encapsulated
97 *
98 * Note: Start and end of the key_mod, src and dst buffers have to be aligned to
99 * the cache line size (ARCH_DMA_MINALIGN) for the CAAM operation to succeed.
100 *
101 * Returns zero on success, negative on error.
102 */
103int blob_encap(u8 *key_mod, u8 *src, u8 *dst, u32 len)
104{
105	int ret, size, i = 0;
106	u32 *desc;
107
108	if (!IS_ALIGNED((uintptr_t)key_mod, ARCH_DMA_MINALIGN) ||
109	    !IS_ALIGNED((uintptr_t)src, ARCH_DMA_MINALIGN) ||
110	    !IS_ALIGNED((uintptr_t)dst, ARCH_DMA_MINALIGN)) {
111		puts("Error: blob_encap: Address arguments are not aligned!\n");
112		return -EINVAL;
113	}
114
115	printf("\nEncapsulating data to form blob\n");
116	desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE);
117	if (!desc) {
118		debug("Not enough memory for descriptor allocation\n");
119		return -ENOMEM;
120	}
121
122	size = ALIGN(16, ARCH_DMA_MINALIGN);
123	flush_dcache_range((unsigned long)key_mod,
124			   (unsigned long)key_mod + size);
125
126	size = ALIGN(len, ARCH_DMA_MINALIGN);
127	flush_dcache_range((unsigned long)src,
128			   (unsigned long)src + size);
129
130	inline_cnstr_jobdesc_blob_encap(desc, key_mod, src, dst, len);
131
132	debug("Descriptor dump:\n");
133	for (i = 0; i < 14; i++)
134		debug("Word[%d]: %08x\n", i, *(desc + i));
135
136	size = ALIGN(sizeof(int) * MAX_CAAM_DESCSIZE, ARCH_DMA_MINALIGN);
137	flush_dcache_range((unsigned long)desc,
138			   (unsigned long)desc + size);
139
140	flush_dcache_range((unsigned long)dst,
141			   (unsigned long)dst + size);
142
143	ret = run_descriptor_jr(desc);
144
145	if (ret) {
146		printf("Error in blob encapsulation: %d\n", ret);
147	} else {
148		size = ALIGN(BLOB_SIZE(len), ARCH_DMA_MINALIGN);
149		invalidate_dcache_range((unsigned long)dst,
150					(unsigned long)dst + size);
151
152		puts("Blob encapsulation successful.\n");
153	}
154
155	free(desc);
156	return ret;
157}
158
159#ifdef CONFIG_CMD_DEKBLOB
160int blob_dek(const u8 *src, u8 *dst, u8 len)
161{
162	int ret, size, i = 0;
163	u32 *desc;
164
165	int out_sz =  WRP_HDR_SIZE + len + KEY_BLOB_SIZE + MAC_SIZE;
166
167	puts("\nEncapsulating provided DEK to form blob\n");
168	desc = memalign(ARCH_DMA_MINALIGN,
169			sizeof(uint32_t) * DEK_BLOB_DESCSIZE);
170	if (!desc) {
171		debug("Not enough memory for descriptor allocation\n");
172		return -ENOMEM;
173	}
174
175	ret = inline_cnstr_jobdesc_blob_dek(desc, src, dst, len);
176	if (ret) {
177		debug("Error in Job Descriptor Construction:  %d\n", ret);
178	} else {
179		size = roundup(sizeof(uint32_t) * DEK_BLOB_DESCSIZE,
180			      ARCH_DMA_MINALIGN);
181		flush_dcache_range((unsigned long)desc,
182				   (unsigned long)desc + size);
183		size = roundup(sizeof(uint8_t) * out_sz, ARCH_DMA_MINALIGN);
184		flush_dcache_range((unsigned long)dst,
185				   (unsigned long)dst + size);
186
187		ret = run_descriptor_jr(desc);
188	}
189
190	if (ret) {
191		debug("Error in Encapsulation %d\n", ret);
192	   goto err;
193	}
194
195	size = roundup(out_sz, ARCH_DMA_MINALIGN);
196	invalidate_dcache_range((unsigned long)dst, (unsigned long)dst+size);
197
198	puts("DEK Blob\n");
199	for (i = 0; i < out_sz; i++)
200		printf("%02X", ((uint8_t *)dst)[i]);
201	printf("\n");
202
203err:
204	free(desc);
205	return ret;
206}
207#endif
208