Merge tag 'tpm-030822' of https://source.denx.de/u-boot/custodians/u-boot-tpm
[platform/kernel/u-boot.git] / arch / arm / mach-k3 / security.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * K3: Security functions
4  *
5  * Copyright (C) 2018-2022 Texas Instruments Incorporated - http://www.ti.com/
6  *      Andrew F. Davis <afd@ti.com>
7  */
8
9 #include <asm/io.h>
10 #include <common.h>
11 #include <cpu_func.h>
12 #include <dm.h>
13 #include <hang.h>
14 #include <image.h>
15 #include <log.h>
16 #include <asm/cache.h>
17 #include <linux/soc/ti/ti_sci_protocol.h>
18 #include <mach/spl.h>
19 #include <spl.h>
20 #include <asm/arch/sys_proto.h>
21
22 #include "common.h"
23
24 static bool ti_secure_cert_detected(void *p_image)
25 {
26         /* Primitive certificate detection, check for DER starting with
27          * two 4-Octet SEQUENCE tags
28          */
29         return (((u8 *)p_image)[0] == 0x30 && ((u8 *)p_image)[1] == 0x82 &&
30                 ((u8 *)p_image)[4] == 0x30 && ((u8 *)p_image)[5] == 0x82);
31 }
32
33 /* Primitive certificate length, assumes one 2-Octet sized SEQUENCE */
34 static size_t ti_secure_cert_length(void *p_image)
35 {
36         size_t seq_length = be16_to_cpu(readw_relaxed(p_image + 2));
37         /* Add 4 for the SEQUENCE tag length */
38         return seq_length + 4;
39 }
40
41 void ti_secure_image_post_process(void **p_image, size_t *p_size)
42 {
43         struct ti_sci_handle *ti_sci = get_ti_sci_handle();
44         struct ti_sci_proc_ops *proc_ops = &ti_sci->ops.proc_ops;
45         size_t cert_length;
46         u64 image_addr;
47         u32 image_size;
48         int ret;
49
50         image_addr = (uintptr_t)*p_image;
51         image_size = *p_size;
52
53         if (!image_size)
54                 return;
55
56         if (get_device_type() == K3_DEVICE_TYPE_GP) {
57                 if (ti_secure_cert_detected(*p_image)) {
58                         printf("Warning: Detected image signing certificate on GP device. "
59                                "Skipping certificate to prevent boot failure. "
60                                "This will fail if the image was also encrypted\n");
61
62                         cert_length = ti_secure_cert_length(*p_image);
63                         if (cert_length > *p_size) {
64                                 printf("Invalid signing certificate size\n");
65                                 return;
66                         }
67
68                         *p_image += cert_length;
69                         *p_size -= cert_length;
70                 }
71
72                 return;
73         }
74
75         if (get_device_type() != K3_DEVICE_TYPE_HS_SE &&
76             !ti_secure_cert_detected(*p_image)) {
77                 printf("Warning: Did not detect image signing certificate. "
78                        "Skipping authentication to prevent boot failure. "
79                        "This will fail on Security Enforcing(HS-SE) devices\n");
80                 return;
81         }
82
83         debug("Authenticating image at address 0x%016llx\n", image_addr);
84         debug("Authenticating image of size %d bytes\n", image_size);
85
86         flush_dcache_range((unsigned long)image_addr,
87                            ALIGN((unsigned long)image_addr + image_size,
88                                  ARCH_DMA_MINALIGN));
89
90         /* Authenticate image */
91         ret = proc_ops->proc_auth_boot_image(ti_sci, &image_addr, &image_size);
92         if (ret) {
93                 printf("Authentication failed!\n");
94                 hang();
95         }
96
97         if (image_size)
98                 invalidate_dcache_range((unsigned long)image_addr,
99                                         ALIGN((unsigned long)image_addr +
100                                               image_size, ARCH_DMA_MINALIGN));
101
102         /*
103          * The image_size returned may be 0 when the authentication process has
104          * moved the image. When this happens no further processing on the
105          * image is needed or often even possible as it may have also been
106          * placed behind a firewall when moved.
107          */
108         *p_size = image_size;
109
110         /*
111          * Output notification of successful authentication to re-assure the
112          * user that the secure code is being processed as expected. However
113          * suppress any such log output in case of building for SPL and booting
114          * via YMODEM. This is done to avoid disturbing the YMODEM serial
115          * protocol transactions.
116          */
117         if (!(IS_ENABLED(CONFIG_SPL_BUILD) &&
118               IS_ENABLED(CONFIG_SPL_YMODEM_SUPPORT) &&
119               spl_boot_device() == BOOT_DEVICE_UART))
120                 printf("Authentication passed\n");
121 }