blob: d9364d0ebe3ce8c673b443642dc3a5c4a06f4be8 [file] [log] [blame]
Martin Rothc7acf162020-05-28 00:44:50 -06001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <2crypto.h>
4#include <2return_codes.h>
5#include <bl_uapp/bl_syscall_public.h>
6#include <commonlib/bsd/helpers.h>
7#include <console/console.h>
8#include "psp_verstage.h"
9#include <stddef.h>
10#include <string.h>
Kangheui Won362ec8d2020-10-02 16:12:02 +100011#include <swab.h>
Martin Rothc7acf162020-05-28 00:44:50 -060012#include <vb2_api.h>
13
14static struct SHA_GENERIC_DATA_T sha_op;
15static uint32_t sha_op_size_remaining;
16static uint8_t __attribute__((aligned(32))) sha_hash[64];
17
18vb2_error_t vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg, uint32_t data_size)
19{
20 printk(BIOS_DEBUG, "Calculating hash of %d bytes\n", data_size);
21
22 sha_op_size_remaining = data_size;
23
24 if (hash_alg == VB2_HASH_SHA256) {
25 sha_op.SHAType = SHA_TYPE_256;
26 sha_op.DigestLen = 32;
27 } else if (hash_alg == VB2_HASH_SHA512) {
28 sha_op.SHAType = SHA_TYPE_512;
29 sha_op.DigestLen = 64;
30 } else {
31 printk(BIOS_INFO, "Unsupported hash_alg %d!\n", hash_alg);
32 return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED;
33 }
34
35 /* Set init flag for first operation */
36 sha_op.Init = 1;
37
38 /* Clear eom flag until last operation */
39 sha_op.Eom = 0;
40
41 /* Need documentation on this b:157610147 */
42 sha_op.DataMemType = 2;
43
44 sha_op.Digest = sha_hash;
45
46 sha_op.IntermediateDigest = NULL;
47
48 sha_op.IntermediateMsgLen = 0;
49
50 return VB2_SUCCESS;
51}
52
53vb2_error_t vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size)
54{
55 uint32_t retval;
56 sha_op.Data = (uint8_t *) buf;
57
58 if (!sha_op_size_remaining) {
59 printk(BIOS_ERR, "ERROR: got more data than expected.\n");
60 return VB2_ERROR_UNKNOWN;
61 }
62
63 while (size) {
64 sha_op.DataLen = size;
65
66 sha_op_size_remaining -= sha_op.DataLen;
67
68 /* Set eom flag for final operation */
69 if (sha_op_size_remaining == 0)
70 sha_op.Eom = 1;
71
72 retval = svc_crypto_sha(&sha_op, SHA_GENERIC);
73 if (retval) {
74 printk(BIOS_ERR, "ERROR: HW crypto failed - errorcode: %#x\n",
75 retval);
76 return VB2_ERROR_UNKNOWN;
77 }
78
79 /* Clear init flag after first operation */
80 if (sha_op.Init == 1)
81 sha_op.Init = 0;
82
83 size -= sha_op.DataLen;
84 }
85
86 return VB2_SUCCESS;
87}
88
89/* Copy the hash back to verstage */
90vb2_error_t vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size)
91{
92 if (sha_op.Eom == 0) {
93 printk(BIOS_ERR, "ERROR: Got less data than expected.\n");
94 return VB2_ERROR_UNKNOWN;
95 }
96
97 if (digest_size != sha_op.DigestLen) {
98 printk(BIOS_ERR, "ERROR: Digest size does not match expected length.\n");
99 return VB2_ERROR_UNKNOWN;
100 }
101
102 memcpy(digest, sha_hash, digest_size);
103
104 return VB2_SUCCESS;
105}
Kangheui Won07de9082020-08-14 14:37:53 +1000106
Kangheui Won362ec8d2020-10-02 16:12:02 +1000107vb2_error_t vb2ex_hwcrypto_modexp(const struct vb2_public_key *key,
108 uint8_t *inout,
109 uint32_t *workbuf32, int exp)
Kangheui Won07de9082020-08-14 14:37:53 +1000110{
Kangheui Won362ec8d2020-10-02 16:12:02 +1000111 /* workbuf32 is guaranteed to be a length of
112 * 3 * key->arrsize * sizeof(uint32_t).
113 * Since PSP expects everything in LE and *inout is BE array,
114 * we'll use workbuf for temporary buffer for endian conversion.
115 */
116 MOD_EXP_PARAMS mod_exp_param;
117 unsigned int key_bytes = key->arrsize * sizeof(uint32_t);
118 uint32_t *sig_swapped = workbuf32;
119 uint32_t *output_buffer = &workbuf32[key->arrsize];
120 uint32_t *inout_32 = (uint32_t *)inout;
Kangheui Won07de9082020-08-14 14:37:53 +1000121 uint32_t retval;
Kangheui Won362ec8d2020-10-02 16:12:02 +1000122 uint32_t i;
Kangheui Won07de9082020-08-14 14:37:53 +1000123
Kangheui Won362ec8d2020-10-02 16:12:02 +1000124 /* PSP only supports 2K and 4K moduli */
Kangheui Won07de9082020-08-14 14:37:53 +1000125 if (key->sig_alg != VB2_SIG_RSA2048 &&
126 key->sig_alg != VB2_SIG_RSA2048_EXP3 &&
127 key->sig_alg != VB2_SIG_RSA4096) {
128 return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED;
129 }
130
Kangheui Won362ec8d2020-10-02 16:12:02 +1000131 for (i = 0; i < key->arrsize; i++)
132 sig_swapped[i] = swab32(inout_32[key->arrsize - i - 1]);
Kangheui Won07de9082020-08-14 14:37:53 +1000133
Kangheui Won362ec8d2020-10-02 16:12:02 +1000134 mod_exp_param.pExponent = (char *)&exp;
135 mod_exp_param.ExpSize = sizeof(exp);
136 mod_exp_param.pModulus = (char *)key->n;
137 mod_exp_param.ModulusSize = key_bytes;
138 mod_exp_param.pMessage = (char *)sig_swapped;
139 mod_exp_param.pOutput = (char *)output_buffer;
Kangheui Won07de9082020-08-14 14:37:53 +1000140
Kangheui Won362ec8d2020-10-02 16:12:02 +1000141 retval = svc_modexp(&mod_exp_param);
Kangheui Won07de9082020-08-14 14:37:53 +1000142 if (retval) {
143 printk(BIOS_ERR, "ERROR: HW crypto failed - errorcode: %#x\n",
144 retval);
Kangheui Won362ec8d2020-10-02 16:12:02 +1000145 return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED;
Kangheui Won07de9082020-08-14 14:37:53 +1000146 }
147
Kangheui Won362ec8d2020-10-02 16:12:02 +1000148 /* vboot expects results in *inout with BE, so copy & convert. */
149 for (i = 0; i < key->arrsize; i++)
150 inout_32[i] = swab32(output_buffer[key->arrsize - i - 1]);
151
Kangheui Won07de9082020-08-14 14:37:53 +1000152 return VB2_SUCCESS;
153}