Commit | Line | Data |
---|---|---|
4c1ec1f9 YK |
1 | /* |
2 | * CAAM/SEC 4.x functions for handling key-generation jobs | |
3 | * | |
4 | * Copyright 2008-2011 Freescale Semiconductor, Inc. | |
5 | * | |
6 | */ | |
7 | #include "compat.h" | |
8 | #include "jr.h" | |
9 | #include "error.h" | |
10 | #include "desc_constr.h" | |
11 | #include "key_gen.h" | |
12 | ||
6655cb8e HG |
13 | /** |
14 | * split_key_len - Compute MDHA split key length for a given algorithm | |
15 | * @hash: Hashing algorithm selection, one of OP_ALG_ALGSEL_* - MD5, SHA1, | |
16 | * SHA224, SHA384, SHA512. | |
17 | * | |
18 | * Return: MDHA split key length | |
19 | */ | |
20 | static inline u32 split_key_len(u32 hash) | |
21 | { | |
22 | /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */ | |
23 | static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 }; | |
24 | u32 idx; | |
25 | ||
26 | idx = (hash & OP_ALG_ALGSEL_SUBMASK) >> OP_ALG_ALGSEL_SHIFT; | |
27 | ||
28 | return (u32)(mdpadlen[idx] * 2); | |
29 | } | |
30 | ||
31 | /** | |
32 | * split_key_pad_len - Compute MDHA split key pad length for a given algorithm | |
33 | * @hash: Hashing algorithm selection, one of OP_ALG_ALGSEL_* - MD5, SHA1, | |
34 | * SHA224, SHA384, SHA512. | |
35 | * | |
36 | * Return: MDHA split key pad length | |
37 | */ | |
38 | static inline u32 split_key_pad_len(u32 hash) | |
39 | { | |
40 | return ALIGN(split_key_len(hash), 16); | |
41 | } | |
42 | ||
4c1ec1f9 YK |
43 | void split_key_done(struct device *dev, u32 *desc, u32 err, |
44 | void *context) | |
45 | { | |
46 | struct split_key_result *res = context; | |
47 | ||
48 | #ifdef DEBUG | |
49 | dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err); | |
50 | #endif | |
51 | ||
fa9659cd MV |
52 | if (err) |
53 | caam_jr_strstatus(dev, err); | |
4c1ec1f9 YK |
54 | |
55 | res->err = err; | |
56 | ||
57 | complete(&res->completion); | |
58 | } | |
59 | EXPORT_SYMBOL(split_key_done); | |
60 | /* | |
61 | get a split ipad/opad key | |
62 | ||
63 | Split key generation----------------------------------------------- | |
64 | ||
65 | [00] 0xb0810008 jobdesc: stidx=1 share=never len=8 | |
66 | [01] 0x04000014 key: class2->keyreg len=20 | |
67 | @0xffe01000 | |
68 | [03] 0x84410014 operation: cls2-op sha1 hmac init dec | |
69 | [04] 0x24940000 fifold: class2 msgdata-last2 len=0 imm | |
70 | [05] 0xa4000001 jump: class2 local all ->1 [06] | |
71 | [06] 0x64260028 fifostr: class2 mdsplit-jdk len=40 | |
72 | @0xffe04000 | |
73 | */ | |
db57656b | 74 | int gen_split_key(struct device *jrdev, u8 *key_out, |
6655cb8e HG |
75 | struct alginfo * const adata, const u8 *key_in, u32 keylen, |
76 | int max_keylen) | |
4c1ec1f9 YK |
77 | { |
78 | u32 *desc; | |
79 | struct split_key_result result; | |
80 | dma_addr_t dma_addr_in, dma_addr_out; | |
738459e3 | 81 | int ret = -ENOMEM; |
4c1ec1f9 | 82 | |
6655cb8e HG |
83 | adata->keylen = split_key_len(adata->algtype & OP_ALG_ALGSEL_MASK); |
84 | adata->keylen_pad = split_key_pad_len(adata->algtype & | |
85 | OP_ALG_ALGSEL_MASK); | |
86 | ||
87 | #ifdef DEBUG | |
88 | dev_err(jrdev, "split keylen %d split keylen padded %d\n", | |
89 | adata->keylen, adata->keylen_pad); | |
90 | print_hex_dump(KERN_ERR, "ctx.key@" __stringify(__LINE__)": ", | |
91 | DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1); | |
92 | #endif | |
93 | ||
94 | if (adata->keylen_pad > max_keylen) | |
95 | return -EINVAL; | |
96 | ||
4c1ec1f9 | 97 | desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA); |
2af8f4a2 KP |
98 | if (!desc) { |
99 | dev_err(jrdev, "unable to allocate key input memory\n"); | |
738459e3 | 100 | return ret; |
2af8f4a2 | 101 | } |
4c1ec1f9 | 102 | |
4c1ec1f9 YK |
103 | dma_addr_in = dma_map_single(jrdev, (void *)key_in, keylen, |
104 | DMA_TO_DEVICE); | |
105 | if (dma_mapping_error(jrdev, dma_addr_in)) { | |
106 | dev_err(jrdev, "unable to map key input memory\n"); | |
738459e3 | 107 | goto out_free; |
4c1ec1f9 | 108 | } |
738459e3 | 109 | |
db57656b | 110 | dma_addr_out = dma_map_single(jrdev, key_out, adata->keylen_pad, |
738459e3 CS |
111 | DMA_FROM_DEVICE); |
112 | if (dma_mapping_error(jrdev, dma_addr_out)) { | |
113 | dev_err(jrdev, "unable to map key output memory\n"); | |
114 | goto out_unmap_in; | |
115 | } | |
116 | ||
117 | init_job_desc(desc, 0); | |
4c1ec1f9 YK |
118 | append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG); |
119 | ||
120 | /* Sets MDHA up into an HMAC-INIT */ | |
488ebc3a HG |
121 | append_operation(desc, (adata->algtype & OP_ALG_ALGSEL_MASK) | |
122 | OP_ALG_AAI_HMAC | OP_TYPE_CLASS2_ALG | OP_ALG_DECRYPT | | |
123 | OP_ALG_AS_INIT); | |
4c1ec1f9 YK |
124 | |
125 | /* | |
126 | * do a FIFO_LOAD of zero, this will trigger the internal key expansion | |
127 | * into both pads inside MDHA | |
128 | */ | |
129 | append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB | | |
130 | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2); | |
131 | ||
132 | /* | |
133 | * FIFO_STORE with the explicit split-key content store | |
134 | * (0x26 output type) | |
135 | */ | |
db57656b | 136 | append_fifo_store(desc, dma_addr_out, adata->keylen, |
4c1ec1f9 YK |
137 | LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK); |
138 | ||
139 | #ifdef DEBUG | |
514df281 | 140 | print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ", |
4c1ec1f9 | 141 | DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1); |
514df281 | 142 | print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ", |
4c1ec1f9 YK |
143 | DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); |
144 | #endif | |
145 | ||
146 | result.err = 0; | |
147 | init_completion(&result.completion); | |
148 | ||
149 | ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); | |
150 | if (!ret) { | |
151 | /* in progress */ | |
7459e1d2 | 152 | wait_for_completion(&result.completion); |
4c1ec1f9 YK |
153 | ret = result.err; |
154 | #ifdef DEBUG | |
514df281 | 155 | print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ", |
4c1ec1f9 | 156 | DUMP_PREFIX_ADDRESS, 16, 4, key_out, |
db57656b | 157 | adata->keylen_pad, 1); |
4c1ec1f9 YK |
158 | #endif |
159 | } | |
160 | ||
db57656b | 161 | dma_unmap_single(jrdev, dma_addr_out, adata->keylen_pad, |
4c1ec1f9 | 162 | DMA_FROM_DEVICE); |
738459e3 | 163 | out_unmap_in: |
4c1ec1f9 | 164 | dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE); |
738459e3 | 165 | out_free: |
4c1ec1f9 | 166 | kfree(desc); |
4c1ec1f9 YK |
167 | return ret; |
168 | } | |
3b75a2c1 | 169 | EXPORT_SYMBOL(gen_split_key); |