2 * ASPEED Hash and Crypto Engine
4 * Copyright (C) 2021 IBM Corp.
6 * Joel Stanley <joel@jms.id.au>
8 * SPDX-License-Identifier: GPL-2.0-or-later
11 #include "qemu/osdep.h"
13 #include "qemu/error-report.h"
14 #include "hw/misc/aspeed_hace.h"
15 #include "qapi/error.h"
16 #include "migration/vmstate.h"
17 #include "crypto/hash.h"
18 #include "hw/qdev-properties.h"
21 #define R_CRYPT_CMD (0x10 / 4)
23 #define R_STATUS (0x1c / 4)
24 #define HASH_IRQ BIT(9)
25 #define CRYPT_IRQ BIT(12)
26 #define TAG_IRQ BIT(15)
28 #define R_HASH_SRC (0x20 / 4)
29 #define R_HASH_DEST (0x24 / 4)
30 #define R_HASH_SRC_LEN (0x2c / 4)
32 #define R_HASH_CMD (0x30 / 4)
33 /* Hash algorithm selection */
34 #define HASH_ALGO_MASK (BIT(4) | BIT(5) | BIT(6))
35 #define HASH_ALGO_MD5 0
36 #define HASH_ALGO_SHA1 BIT(5)
37 #define HASH_ALGO_SHA224 BIT(6)
38 #define HASH_ALGO_SHA256 (BIT(4) | BIT(6))
39 #define HASH_ALGO_SHA512_SERIES (BIT(5) | BIT(6))
40 /* SHA512 algorithm selection */
41 #define SHA512_HASH_ALGO_MASK (BIT(10) | BIT(11) | BIT(12))
42 #define HASH_ALGO_SHA512_SHA512 0
43 #define HASH_ALGO_SHA512_SHA384 BIT(10)
44 #define HASH_ALGO_SHA512_SHA256 BIT(11)
45 #define HASH_ALGO_SHA512_SHA224 (BIT(10) | BIT(11))
47 #define HASH_HMAC_MASK (BIT(7) | BIT(8))
49 #define HASH_DIGEST_HMAC BIT(7)
50 #define HASH_DIGEST_ACCUM BIT(8)
51 #define HASH_HMAC_KEY (BIT(7) | BIT(8))
52 /* Cascaded operation modes */
54 #define HASH_ONLY2 BIT(0)
55 #define HASH_CRYPT_THEN_HASH BIT(1)
56 #define HASH_HASH_THEN_CRYPT (BIT(0) | BIT(1))
58 #define HASH_IRQ_EN BIT(9)
59 #define HASH_SG_EN BIT(18)
60 /* Scatter-gather data list */
61 #define SG_LIST_LEN_SIZE 4
62 #define SG_LIST_LEN_MASK 0x0FFFFFFF
63 #define SG_LIST_LEN_LAST BIT(31)
64 #define SG_LIST_ADDR_SIZE 4
65 #define SG_LIST_ADDR_MASK 0x7FFFFFFF
66 #define SG_LIST_ENTRY_SIZE (SG_LIST_LEN_SIZE + SG_LIST_ADDR_SIZE)
67 #define ASPEED_HACE_MAX_SG 256 /* max number of entries */
71 QCryptoHashAlgorithm algo
;
73 { HASH_ALGO_MD5
, QCRYPTO_HASH_ALG_MD5
},
74 { HASH_ALGO_SHA1
, QCRYPTO_HASH_ALG_SHA1
},
75 { HASH_ALGO_SHA224
, QCRYPTO_HASH_ALG_SHA224
},
76 { HASH_ALGO_SHA256
, QCRYPTO_HASH_ALG_SHA256
},
77 { HASH_ALGO_SHA512_SERIES
| HASH_ALGO_SHA512_SHA512
, QCRYPTO_HASH_ALG_SHA512
},
78 { HASH_ALGO_SHA512_SERIES
| HASH_ALGO_SHA512_SHA384
, QCRYPTO_HASH_ALG_SHA384
},
79 { HASH_ALGO_SHA512_SERIES
| HASH_ALGO_SHA512_SHA256
, QCRYPTO_HASH_ALG_SHA256
},
82 static int hash_algo_lookup(uint32_t reg
)
86 reg
&= HASH_ALGO_MASK
| SHA512_HASH_ALGO_MASK
;
88 for (i
= 0; i
< ARRAY_SIZE(hash_algo_map
); i
++) {
89 if (reg
== hash_algo_map
[i
].mask
) {
90 return hash_algo_map
[i
].algo
;
97 static void do_hash_operation(AspeedHACEState
*s
, int algo
, bool sg_mode
)
99 struct iovec iov
[ASPEED_HACE_MAX_SG
];
100 g_autofree
uint8_t *digest_buf
;
101 size_t digest_len
= 0;
107 for (i
= 0; !(len
& SG_LIST_LEN_LAST
); i
++) {
111 if (i
== ASPEED_HACE_MAX_SG
) {
112 qemu_log_mask(LOG_GUEST_ERROR
,
113 "aspeed_hace: guest failed to set end of sg list marker\n");
117 src
= s
->regs
[R_HASH_SRC
] + (i
* SG_LIST_ENTRY_SIZE
);
119 len
= address_space_ldl_le(&s
->dram_as
, src
,
120 MEMTXATTRS_UNSPECIFIED
, NULL
);
122 addr
= address_space_ldl_le(&s
->dram_as
, src
+ SG_LIST_LEN_SIZE
,
123 MEMTXATTRS_UNSPECIFIED
, NULL
);
124 addr
&= SG_LIST_ADDR_MASK
;
126 iov
[i
].iov_len
= len
& SG_LIST_LEN_MASK
;
127 plen
= iov
[i
].iov_len
;
128 iov
[i
].iov_base
= address_space_map(&s
->dram_as
, addr
, &plen
, false,
129 MEMTXATTRS_UNSPECIFIED
);
132 hwaddr len
= s
->regs
[R_HASH_SRC_LEN
];
134 iov
[0].iov_len
= len
;
135 iov
[0].iov_base
= address_space_map(&s
->dram_as
, s
->regs
[R_HASH_SRC
],
137 MEMTXATTRS_UNSPECIFIED
);
141 if (qcrypto_hash_bytesv(algo
, iov
, i
, &digest_buf
, &digest_len
, NULL
) < 0) {
142 qemu_log_mask(LOG_GUEST_ERROR
, "%s: qcrypto failed\n", __func__
);
146 if (address_space_write(&s
->dram_as
, s
->regs
[R_HASH_DEST
],
147 MEMTXATTRS_UNSPECIFIED
,
148 digest_buf
, digest_len
)) {
149 qemu_log_mask(LOG_GUEST_ERROR
,
150 "aspeed_hace: address space write failed\n");
154 address_space_unmap(&s
->dram_as
, iov
[i
- 1].iov_base
,
155 iov
[i
- 1].iov_len
, false,
160 * Set status bits to indicate completion. Testing shows hardware sets
161 * these irrespective of HASH_IRQ_EN.
163 s
->regs
[R_STATUS
] |= HASH_IRQ
;
166 static uint64_t aspeed_hace_read(void *opaque
, hwaddr addr
, unsigned int size
)
168 AspeedHACEState
*s
= ASPEED_HACE(opaque
);
172 if (addr
>= ASPEED_HACE_NR_REGS
) {
173 qemu_log_mask(LOG_GUEST_ERROR
,
174 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx
"\n",
175 __func__
, addr
<< 2);
179 return s
->regs
[addr
];
182 static void aspeed_hace_write(void *opaque
, hwaddr addr
, uint64_t data
,
185 AspeedHACEState
*s
= ASPEED_HACE(opaque
);
186 AspeedHACEClass
*ahc
= ASPEED_HACE_GET_CLASS(s
);
190 if (addr
>= ASPEED_HACE_NR_REGS
) {
191 qemu_log_mask(LOG_GUEST_ERROR
,
192 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx
"\n",
193 __func__
, addr
<< 2);
199 if (data
& HASH_IRQ
) {
202 if (s
->regs
[addr
] & HASH_IRQ
) {
203 qemu_irq_lower(s
->irq
);
208 data
&= ahc
->src_mask
;
211 data
&= ahc
->dest_mask
;
218 data
&= ahc
->hash_mask
;
220 if ((data
& HASH_HMAC_MASK
)) {
221 qemu_log_mask(LOG_UNIMP
,
222 "%s: HMAC engine command mode %"PRIx64
" not implemented",
223 __func__
, (data
& HASH_HMAC_MASK
) >> 8);
226 qemu_log_mask(LOG_UNIMP
,
227 "%s: Cascaded mode not implemented",
230 algo
= hash_algo_lookup(data
);
232 qemu_log_mask(LOG_GUEST_ERROR
,
233 "%s: Invalid hash algorithm selection 0x%"PRIx64
"\n",
234 __func__
, data
& ahc
->hash_mask
);
237 do_hash_operation(s
, algo
, data
& HASH_SG_EN
);
239 if (data
& HASH_IRQ_EN
) {
240 qemu_irq_raise(s
->irq
);
245 qemu_log_mask(LOG_UNIMP
, "%s: Crypt commands not implemented\n",
252 s
->regs
[addr
] = data
;
255 static const MemoryRegionOps aspeed_hace_ops
= {
256 .read
= aspeed_hace_read
,
257 .write
= aspeed_hace_write
,
258 .endianness
= DEVICE_LITTLE_ENDIAN
,
260 .min_access_size
= 1,
261 .max_access_size
= 4,
265 static void aspeed_hace_reset(DeviceState
*dev
)
267 struct AspeedHACEState
*s
= ASPEED_HACE(dev
);
269 memset(s
->regs
, 0, sizeof(s
->regs
));
272 static void aspeed_hace_realize(DeviceState
*dev
, Error
**errp
)
274 AspeedHACEState
*s
= ASPEED_HACE(dev
);
275 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
277 sysbus_init_irq(sbd
, &s
->irq
);
279 memory_region_init_io(&s
->iomem
, OBJECT(s
), &aspeed_hace_ops
, s
,
280 TYPE_ASPEED_HACE
, 0x1000);
283 error_setg(errp
, TYPE_ASPEED_HACE
": 'dram' link not set");
287 address_space_init(&s
->dram_as
, s
->dram_mr
, "dram");
289 sysbus_init_mmio(sbd
, &s
->iomem
);
292 static Property aspeed_hace_properties
[] = {
293 DEFINE_PROP_LINK("dram", AspeedHACEState
, dram_mr
,
294 TYPE_MEMORY_REGION
, MemoryRegion
*),
295 DEFINE_PROP_END_OF_LIST(),
299 static const VMStateDescription vmstate_aspeed_hace
= {
300 .name
= TYPE_ASPEED_HACE
,
302 .minimum_version_id
= 1,
303 .fields
= (VMStateField
[]) {
304 VMSTATE_UINT32_ARRAY(regs
, AspeedHACEState
, ASPEED_HACE_NR_REGS
),
305 VMSTATE_END_OF_LIST(),
309 static void aspeed_hace_class_init(ObjectClass
*klass
, void *data
)
311 DeviceClass
*dc
= DEVICE_CLASS(klass
);
313 dc
->realize
= aspeed_hace_realize
;
314 dc
->reset
= aspeed_hace_reset
;
315 device_class_set_props(dc
, aspeed_hace_properties
);
316 dc
->vmsd
= &vmstate_aspeed_hace
;
319 static const TypeInfo aspeed_hace_info
= {
320 .name
= TYPE_ASPEED_HACE
,
321 .parent
= TYPE_SYS_BUS_DEVICE
,
322 .instance_size
= sizeof(AspeedHACEState
),
323 .class_init
= aspeed_hace_class_init
,
324 .class_size
= sizeof(AspeedHACEClass
)
327 static void aspeed_ast2400_hace_class_init(ObjectClass
*klass
, void *data
)
329 DeviceClass
*dc
= DEVICE_CLASS(klass
);
330 AspeedHACEClass
*ahc
= ASPEED_HACE_CLASS(klass
);
332 dc
->desc
= "AST2400 Hash and Crypto Engine";
334 ahc
->src_mask
= 0x0FFFFFFF;
335 ahc
->dest_mask
= 0x0FFFFFF8;
336 ahc
->hash_mask
= 0x000003ff; /* No SG or SHA512 modes */
339 static const TypeInfo aspeed_ast2400_hace_info
= {
340 .name
= TYPE_ASPEED_AST2400_HACE
,
341 .parent
= TYPE_ASPEED_HACE
,
342 .class_init
= aspeed_ast2400_hace_class_init
,
345 static void aspeed_ast2500_hace_class_init(ObjectClass
*klass
, void *data
)
347 DeviceClass
*dc
= DEVICE_CLASS(klass
);
348 AspeedHACEClass
*ahc
= ASPEED_HACE_CLASS(klass
);
350 dc
->desc
= "AST2500 Hash and Crypto Engine";
352 ahc
->src_mask
= 0x3fffffff;
353 ahc
->dest_mask
= 0x3ffffff8;
354 ahc
->hash_mask
= 0x000003ff; /* No SG or SHA512 modes */
357 static const TypeInfo aspeed_ast2500_hace_info
= {
358 .name
= TYPE_ASPEED_AST2500_HACE
,
359 .parent
= TYPE_ASPEED_HACE
,
360 .class_init
= aspeed_ast2500_hace_class_init
,
363 static void aspeed_ast2600_hace_class_init(ObjectClass
*klass
, void *data
)
365 DeviceClass
*dc
= DEVICE_CLASS(klass
);
366 AspeedHACEClass
*ahc
= ASPEED_HACE_CLASS(klass
);
368 dc
->desc
= "AST2600 Hash and Crypto Engine";
370 ahc
->src_mask
= 0x7FFFFFFF;
371 ahc
->dest_mask
= 0x7FFFFFF8;
372 ahc
->hash_mask
= 0x00147FFF;
375 static const TypeInfo aspeed_ast2600_hace_info
= {
376 .name
= TYPE_ASPEED_AST2600_HACE
,
377 .parent
= TYPE_ASPEED_HACE
,
378 .class_init
= aspeed_ast2600_hace_class_init
,
381 static void aspeed_hace_register_types(void)
383 type_register_static(&aspeed_ast2400_hace_info
);
384 type_register_static(&aspeed_ast2500_hace_info
);
385 type_register_static(&aspeed_ast2600_hace_info
);
386 type_register_static(&aspeed_hace_info
);
389 type_init(aspeed_hace_register_types
);