Commit 94e3c8c4fd7bfe395fa467973cd647551d6d98c7
Committed by
York Sun
1 parent
7ee8c4795d
Exists in
v2017.01-smarct4x
and in
37 other branches
crypto/fsl - Add progressive hashing support using hardware acceleration.
Currently only normal hashing is supported using hardware acceleration. Added support for progressive hashing using hardware. Signed-off-by: Ruchika Gupta <ruchika.gupta@freescale.com> Signed-off-by: Gaurav Rana <gaurav.rana@freescale.com> CC: Simon Glass <sjg@chromium.org> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: York Sun <yorksun@freescale.com>
Showing 8 changed files with 302 additions and 7 deletions Side-by-side Diff
Kconfig
... | ... | @@ -141,7 +141,9 @@ |
141 | 141 | select RSA |
142 | 142 | help |
143 | 143 | This option enables signature verification of FIT uImages, |
144 | - using a hash signed and verified using RSA. | |
144 | + using a hash signed and verified using RSA. If | |
145 | + CONFIG_SHA_PROG_HW_ACCEL is defined, i.e support for progressive | |
146 | + hashing is available using hardware, RSA library will use it. | |
145 | 147 | See doc/uImage.FIT/signature.txt for more details. |
146 | 148 | |
147 | 149 | config SYS_EXTRA_OPTIONS |
README
... | ... | @@ -3152,8 +3152,18 @@ |
3152 | 3152 | Enable the hash verify command (hash -v). This adds to code |
3153 | 3153 | size a little. |
3154 | 3154 | |
3155 | - CONFIG_SHA1 - support SHA1 hashing | |
3156 | - CONFIG_SHA256 - support SHA256 hashing | |
3155 | + CONFIG_SHA1 - This option enables support of hashing using SHA1 | |
3156 | + algorithm. The hash is calculated in software. | |
3157 | + CONFIG_SHA256 - This option enables support of hashing using | |
3158 | + SHA256 algorithm. The hash is calculated in software. | |
3159 | + CONFIG_SHA_HW_ACCEL - This option enables hardware acceleration | |
3160 | + for SHA1/SHA256 hashing. | |
3161 | + This affects the 'hash' command and also the | |
3162 | + hash_lookup_algo() function. | |
3163 | + CONFIG_SHA_PROG_HW_ACCEL - This option enables | |
3164 | + hardware-acceleration for SHA1/SHA256 progressive hashing. | |
3165 | + Data can be streamed in a block at a time and the hashing | |
3166 | + is performed in hardware. | |
3157 | 3167 | |
3158 | 3168 | Note: There is also a sha1sum command, which should perhaps |
3159 | 3169 | be deprecated in favour of 'hash sha1'. |
... | ... | @@ -3447,8 +3457,10 @@ |
3447 | 3457 | |
3448 | 3458 | CONFIG_FIT_SIGNATURE |
3449 | 3459 | This option enables signature verification of FIT uImages, |
3450 | - using a hash signed and verified using RSA. See | |
3451 | - doc/uImage.FIT/signature.txt for more details. | |
3460 | + using a hash signed and verified using RSA. If | |
3461 | + CONFIG_SHA_PROG_HW_ACCEL is defined, i.e support for progressive | |
3462 | + hashing is available using hardware, RSA library will use it. | |
3463 | + See doc/uImage.FIT/signature.txt for more details. | |
3452 | 3464 | |
3453 | 3465 | WARNING: When relying on signed FIT images with required |
3454 | 3466 | signature check the legacy image format is default |
common/hash.c
... | ... | @@ -127,11 +127,21 @@ |
127 | 127 | SHA1_SUM_LEN, |
128 | 128 | hw_sha1, |
129 | 129 | CHUNKSZ_SHA1, |
130 | +#ifdef CONFIG_SHA_PROG_HW_ACCEL | |
131 | + hw_sha_init, | |
132 | + hw_sha_update, | |
133 | + hw_sha_finish, | |
134 | +#endif | |
130 | 135 | }, { |
131 | 136 | "sha256", |
132 | 137 | SHA256_SUM_LEN, |
133 | 138 | hw_sha256, |
134 | 139 | CHUNKSZ_SHA256, |
140 | +#ifdef CONFIG_SHA_PROG_HW_ACCEL | |
141 | + hw_sha_init, | |
142 | + hw_sha_update, | |
143 | + hw_sha_finish, | |
144 | +#endif | |
135 | 145 | }, |
136 | 146 | #endif |
137 | 147 | #ifdef CONFIG_SHA1 |
drivers/crypto/fsl/fsl_hash.c
... | ... | @@ -10,6 +10,9 @@ |
10 | 10 | #include "jobdesc.h" |
11 | 11 | #include "desc.h" |
12 | 12 | #include "jr.h" |
13 | +#include "fsl_hash.h" | |
14 | +#include <hw_sha.h> | |
15 | +#include <asm-generic/errno.h> | |
13 | 16 | |
14 | 17 | #define CRYPTO_MAX_ALG_NAME 80 |
15 | 18 | #define SHA1_DIGEST_SIZE 20 |
... | ... | @@ -39,6 +42,122 @@ |
39 | 42 | }, |
40 | 43 | }; |
41 | 44 | |
45 | +static enum caam_hash_algos get_hash_type(struct hash_algo *algo) | |
46 | +{ | |
47 | + if (!strcmp(algo->name, driver_hash[SHA1].name)) | |
48 | + return SHA1; | |
49 | + else | |
50 | + return SHA256; | |
51 | +} | |
52 | + | |
53 | +/* Create the context for progressive hashing using h/w acceleration. | |
54 | + * | |
55 | + * @ctxp: Pointer to the pointer of the context for hashing | |
56 | + * @caam_algo: Enum for SHA1 or SHA256 | |
57 | + * @return 0 if ok, -ENOMEM on error | |
58 | + */ | |
59 | +static int caam_hash_init(void **ctxp, enum caam_hash_algos caam_algo) | |
60 | +{ | |
61 | + *ctxp = calloc(1, sizeof(struct sha_ctx)); | |
62 | + if (*ctxp == NULL) { | |
63 | + debug("Cannot allocate memory for context\n"); | |
64 | + return -ENOMEM; | |
65 | + } | |
66 | + return 0; | |
67 | +} | |
68 | + | |
69 | +/* | |
70 | + * Update sg table for progressive hashing using h/w acceleration | |
71 | + * | |
72 | + * The context is freed by this function if an error occurs. | |
73 | + * We support at most 32 Scatter/Gather Entries. | |
74 | + * | |
75 | + * @hash_ctx: Pointer to the context for hashing | |
76 | + * @buf: Pointer to the buffer being hashed | |
77 | + * @size: Size of the buffer being hashed | |
78 | + * @is_last: 1 if this is the last update; 0 otherwise | |
79 | + * @caam_algo: Enum for SHA1 or SHA256 | |
80 | + * @return 0 if ok, -EINVAL on error | |
81 | + */ | |
82 | +static int caam_hash_update(void *hash_ctx, const void *buf, | |
83 | + unsigned int size, int is_last, | |
84 | + enum caam_hash_algos caam_algo) | |
85 | +{ | |
86 | + uint32_t final = 0; | |
87 | + dma_addr_t addr = virt_to_phys((void *)buf); | |
88 | + struct sha_ctx *ctx = hash_ctx; | |
89 | + | |
90 | + if (ctx->sg_num >= MAX_SG_32) { | |
91 | + free(ctx); | |
92 | + return -EINVAL; | |
93 | + } | |
94 | + | |
95 | +#ifdef CONFIG_PHYS_64BIT | |
96 | + ctx->sg_tbl[ctx->sg_num].addr_hi = addr >> 32; | |
97 | +#else | |
98 | + ctx->sg_tbl[ctx->sg_num].addr_hi = 0x0; | |
99 | +#endif | |
100 | + ctx->sg_tbl[ctx->sg_num].addr_lo = addr; | |
101 | + | |
102 | + sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag, | |
103 | + (size & SG_ENTRY_LENGTH_MASK)); | |
104 | + | |
105 | + ctx->sg_num++; | |
106 | + | |
107 | + if (is_last) { | |
108 | + final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) | | |
109 | + SG_ENTRY_FINAL_BIT; | |
110 | + sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final); | |
111 | + } | |
112 | + | |
113 | + return 0; | |
114 | +} | |
115 | + | |
116 | +/* | |
117 | + * Perform progressive hashing on the given buffer and copy hash at | |
118 | + * destination buffer | |
119 | + * | |
120 | + * The context is freed after completion of hash operation. | |
121 | + * | |
122 | + * @hash_ctx: Pointer to the context for hashing | |
123 | + * @dest_buf: Pointer to the destination buffer where hash is to be copied | |
124 | + * @size: Size of the buffer being hashed | |
125 | + * @caam_algo: Enum for SHA1 or SHA256 | |
126 | + * @return 0 if ok, -EINVAL on error | |
127 | + */ | |
128 | +static int caam_hash_finish(void *hash_ctx, void *dest_buf, | |
129 | + int size, enum caam_hash_algos caam_algo) | |
130 | +{ | |
131 | + uint32_t len = 0; | |
132 | + struct sha_ctx *ctx = hash_ctx; | |
133 | + int i = 0, ret = 0; | |
134 | + | |
135 | + if (size < driver_hash[caam_algo].digestsize) { | |
136 | + free(ctx); | |
137 | + return -EINVAL; | |
138 | + } | |
139 | + | |
140 | + for (i = 0; i < ctx->sg_num; i++) | |
141 | + len += (sec_in32(&ctx->sg_tbl[i].len_flag) & | |
142 | + SG_ENTRY_LENGTH_MASK); | |
143 | + | |
144 | + inline_cnstr_jobdesc_hash(ctx->sha_desc, (uint8_t *)ctx->sg_tbl, len, | |
145 | + ctx->hash, | |
146 | + driver_hash[caam_algo].alg_type, | |
147 | + driver_hash[caam_algo].digestsize, | |
148 | + 1); | |
149 | + | |
150 | + ret = run_descriptor_jr(ctx->sha_desc); | |
151 | + | |
152 | + if (ret) | |
153 | + debug("Error %x\n", ret); | |
154 | + else | |
155 | + memcpy(dest_buf, ctx->hash, sizeof(ctx->hash)); | |
156 | + | |
157 | + free(ctx); | |
158 | + return ret; | |
159 | +} | |
160 | + | |
42 | 161 | int caam_hash(const unsigned char *pbuf, unsigned int buf_len, |
43 | 162 | unsigned char *pout, enum caam_hash_algos algo) |
44 | 163 | { |
... | ... | @@ -48,7 +167,7 @@ |
48 | 167 | desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE); |
49 | 168 | if (!desc) { |
50 | 169 | debug("Not enough memory for descriptor allocation\n"); |
51 | - return -1; | |
170 | + return -ENOMEM; | |
52 | 171 | } |
53 | 172 | |
54 | 173 | inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout, |
... | ... | @@ -74,5 +193,22 @@ |
74 | 193 | { |
75 | 194 | if (caam_hash(pbuf, buf_len, pout, SHA1)) |
76 | 195 | printf("CAAM was not setup properly or it is faulty\n"); |
196 | +} | |
197 | + | |
198 | +int hw_sha_init(struct hash_algo *algo, void **ctxp) | |
199 | +{ | |
200 | + return caam_hash_init(ctxp, get_hash_type(algo)); | |
201 | +} | |
202 | + | |
203 | +int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf, | |
204 | + unsigned int size, int is_last) | |
205 | +{ | |
206 | + return caam_hash_update(ctx, buf, size, is_last, get_hash_type(algo)); | |
207 | +} | |
208 | + | |
209 | +int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf, | |
210 | + int size) | |
211 | +{ | |
212 | + return caam_hash_finish(ctx, dest_buf, size, get_hash_type(algo)); | |
77 | 213 | } |
drivers/crypto/fsl/fsl_hash.h
1 | +/* | |
2 | + * Copyright 2014 Freescale Semiconductor, Inc. | |
3 | + * | |
4 | + * SPDX-License-Identifier: GPL-2.0+ | |
5 | + * | |
6 | + */ | |
7 | + | |
8 | +#ifndef _SHA_H | |
9 | +#define _SHA_H | |
10 | + | |
11 | +#include <fsl_sec.h> | |
12 | +#include <hash.h> | |
13 | +#include "jr.h" | |
14 | + | |
15 | +/* We support at most 32 Scatter/Gather Entries.*/ | |
16 | +#define MAX_SG_32 32 | |
17 | + | |
18 | +/* | |
19 | + * Hash context contains the following fields | |
20 | + * @sha_desc: Sha Descriptor | |
21 | + * @sg_num: number of entries in sg table | |
22 | + * @len: total length of buffer | |
23 | + * @sg_tbl: sg entry table | |
24 | + * @hash: index to the hash calculated | |
25 | + */ | |
26 | +struct sha_ctx { | |
27 | + uint32_t sha_desc[64]; | |
28 | + uint32_t sg_num; | |
29 | + uint32_t len; | |
30 | + struct sg_entry sg_tbl[MAX_SG_32]; | |
31 | + u8 hash[HASH_MAX_DIGEST_SIZE]; | |
32 | +}; | |
33 | + | |
34 | +#endif |
include/fsl_sec.h
... | ... | @@ -175,6 +175,32 @@ |
175 | 175 | u32 jrcr; |
176 | 176 | }; |
177 | 177 | |
178 | +/* | |
179 | + * Scatter Gather Entry - Specifies the the Scatter Gather Format | |
180 | + * related information | |
181 | + */ | |
182 | +struct sg_entry { | |
183 | +#ifdef CONFIG_SYS_FSL_SEC_LE | |
184 | + uint32_t addr_lo; /* Memory Address - lo */ | |
185 | + uint16_t addr_hi; /* Memory Address of start of buffer - hi */ | |
186 | + uint16_t reserved_zero; | |
187 | +#else | |
188 | + uint16_t reserved_zero; | |
189 | + uint16_t addr_hi; /* Memory Address of start of buffer - hi */ | |
190 | + uint32_t addr_lo; /* Memory Address - lo */ | |
191 | +#endif | |
192 | + | |
193 | + uint32_t len_flag; /* Length of the data in the frame */ | |
194 | +#define SG_ENTRY_LENGTH_MASK 0x3FFFFFFF | |
195 | +#define SG_ENTRY_EXTENSION_BIT 0x80000000 | |
196 | +#define SG_ENTRY_FINAL_BIT 0x40000000 | |
197 | + uint32_t bpid_offset; | |
198 | +#define SG_ENTRY_BPID_MASK 0x00FF0000 | |
199 | +#define SG_ENTRY_BPID_SHIFT 16 | |
200 | +#define SG_ENTRY_OFFSET_MASK 0x00001FFF | |
201 | +#define SG_ENTRY_OFFSET_SHIFT 0 | |
202 | +}; | |
203 | + | |
178 | 204 | int sec_init(void); |
179 | 205 | #endif |
180 | 206 |
include/hw_sha.h
... | ... | @@ -7,8 +7,8 @@ |
7 | 7 | */ |
8 | 8 | #ifndef __HW_SHA_H |
9 | 9 | #define __HW_SHA_H |
10 | +#include <hash.h> | |
10 | 11 | |
11 | - | |
12 | 12 | /** |
13 | 13 | * Computes hash value of input pbuf using h/w acceleration |
14 | 14 | * |
... | ... | @@ -34,5 +34,44 @@ |
34 | 34 | */ |
35 | 35 | void hw_sha1(const uchar * in_addr, uint buflen, |
36 | 36 | uchar * out_addr, uint chunk_size); |
37 | + | |
38 | +/* | |
39 | + * Create the context for sha progressive hashing using h/w acceleration | |
40 | + * | |
41 | + * @algo: Pointer to the hash_algo struct | |
42 | + * @ctxp: Pointer to the pointer of the context for hashing | |
43 | + * @return 0 if ok, -ve on error | |
44 | + */ | |
45 | +int hw_sha_init(struct hash_algo *algo, void **ctxp); | |
46 | + | |
47 | +/* | |
48 | + * Update buffer for sha progressive hashing using h/w acceleration | |
49 | + * | |
50 | + * The context is freed by this function if an error occurs. | |
51 | + * | |
52 | + * @algo: Pointer to the hash_algo struct | |
53 | + * @ctx: Pointer to the context for hashing | |
54 | + * @buf: Pointer to the buffer being hashed | |
55 | + * @size: Size of the buffer being hashed | |
56 | + * @is_last: 1 if this is the last update; 0 otherwise | |
57 | + * @return 0 if ok, -ve on error | |
58 | + */ | |
59 | +int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf, | |
60 | + unsigned int size, int is_last); | |
61 | + | |
62 | +/* | |
63 | + * Copy sha hash result at destination location | |
64 | + * | |
65 | + * The context is freed after completion of hash operation or after an error. | |
66 | + * | |
67 | + * @algo: Pointer to the hash_algo struct | |
68 | + * @ctx: Pointer to the context for hashing | |
69 | + * @dest_buf: Pointer to the destination buffer where hash is to be copied | |
70 | + * @size: Size of the buffer being hashed | |
71 | + * @return 0 if ok, -ve on error | |
72 | + */ | |
73 | +int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf, | |
74 | + int size); | |
75 | + | |
37 | 76 | #endif |
lib/Kconfig
... | ... | @@ -29,5 +29,41 @@ |
29 | 29 | |
30 | 30 | source lib/rsa/Kconfig |
31 | 31 | |
32 | +menu "Hashing Support" | |
33 | + | |
34 | +config SHA1 | |
35 | + bool "Enable SHA1 support" | |
36 | + help | |
37 | + This option enables support of hashing using SHA1 algorithm. | |
38 | + The hash is calculated in software. | |
39 | + The SHA1 algorithm produces a 160-bit (20-byte) hash value | |
40 | + (digest). | |
41 | + | |
42 | +config SHA256 | |
43 | + bool "Enable SHA256 support" | |
44 | + help | |
45 | + This option enables support of hashing using SHA256 algorithm. | |
46 | + The hash is calculated in software. | |
47 | + The SHA256 algorithm produces a 256-bit (32-byte) hash value | |
48 | + (digest). | |
49 | + | |
50 | +config SHA_HW_ACCEL | |
51 | + bool "Enable hashing using hardware" | |
52 | + help | |
53 | + This option enables hardware acceleration | |
54 | + for SHA1/SHA256 hashing. | |
55 | + This affects the 'hash' command and also the | |
56 | + hash_lookup_algo() function. | |
57 | + | |
58 | +config SHA_PROG_HW_ACCEL | |
59 | + bool "Enable Progressive hashing support using hardware" | |
60 | + depends on SHA_HW_ACCEL | |
61 | + help | |
62 | + This option enables hardware-acceleration for | |
63 | + SHA1/SHA256 progressive hashing. | |
64 | + Data can be streamed in a block at a time and the hashing | |
65 | + is performed in hardware. | |
66 | +endmenu | |
67 | + | |
32 | 68 | endmenu |
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 089df1
-
mentioned in commit 6921d2