1 /* Copyright 2013-2018 IBM Corp.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * 	http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12  * implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef pr_fmt
18 #define pr_fmt(fmt) "STB: " fmt
19 #endif
20 
21 #include <skiboot.h>
22 #include <device.h>
23 #include <nvram.h>
24 #include <opal-api.h>
25 #include <inttypes.h>
26 #include "secureboot.h"
27 
28 static const void* hw_key_hash = NULL;
29 static size_t hw_key_hash_size;
30 static bool secure_mode = false;
31 static bool secure_init = false;
32 static unsigned int level = PR_ERR;
33 
34 static struct {
35 	enum secureboot_version version;
36 	const char *compat;
37 } secureboot_map[] = {
38 	{ IBM_SECUREBOOT_V1, "ibm,secureboot-v1" },
39 	{ IBM_SECUREBOOT_SOFTROM, "ibm,secureboot-v1-softrom" },
40 	{ IBM_SECUREBOOT_V2, "ibm,secureboot-v2" },
41 };
42 
secureboot_enforce(void)43 static void secureboot_enforce(void)
44 {
45 	/* Sanity check */
46 	if (!secure_mode)
47 		return;
48 
49 	/*
50 	 * TODO: Ideally, the BMC should decide what security policy to apply
51 	 * (power off, reboot, switch PNOR sides, etc). We may need to provide
52 	 * extra info to BMC other than just abort.  Terminate Immediate
53 	 * Attention ? (TI)
54 	 */
55 	prlog(PR_EMERG, "secure mode enforced, aborting.\n");
56 	abort();
57 }
58 
secureboot_is_compatible(struct dt_node * node,int * version,const char ** compat)59 bool secureboot_is_compatible(struct dt_node *node, int *version, const char **compat)
60 {
61 	int i;
62 
63 	if (!node)
64 		return false;
65 
66 	for (i = 0; i < ARRAY_SIZE(secureboot_map); i++) {
67 		if (dt_node_is_compatible(node, secureboot_map[i].compat)) {
68 			if (version)
69 				*version = secureboot_map[i].version;
70 			if (compat)
71 				*compat = secureboot_map[i].compat;
72 			return true;
73 		}
74 	}
75 	return false;
76 }
77 
secureboot_init(void)78 void secureboot_init(void)
79 {
80 	struct dt_node *node;
81 	const char *hash_algo;
82 	const char *compat = NULL;
83 	int version;
84 	size_t size;
85 
86 	node = dt_find_by_path(dt_root, "/ibm,secureboot");
87 	if (!node) {
88 		prlog(PR_NOTICE, "secure boot not supported\n");
89 		return;
90 	}
91 
92 	if (!secureboot_is_compatible(node, &version, &compat)) {
93 		/**
94 		 * @fwts-label SecureBootNotCompatible
95 		 * @fwts-advice Compatible secureboot driver not found. Probably,
96 		 * hostboot/mambo/skiboot has updated the
97 		 * /ibm,secureboot/compatible without adding a driver that
98 		 * supports it.
99 		 */
100 		prlog(PR_ERR, "%s FAILED, /ibm,secureboot not compatible.\n",
101 		      __func__);
102 		return;
103 	}
104 
105 	prlog(PR_DEBUG, "Found %s\n", compat);
106 
107 	if (nvram_query_eq_dangerous("force-secure-mode", "always")) {
108 		secure_mode = true;
109 		prlog(PR_NOTICE, "secure mode on (FORCED by nvram)\n");
110 	} else {
111 		secure_mode = dt_has_node_property(node, "secure-enabled", NULL);
112 		prlog(PR_INFO, "secure mode %s\n",
113 		      secure_mode ? "on" : "off");
114 	}
115 
116 	/* Use emergency log level only when secure mode is ON */
117         if (secure_mode)
118                 level = PR_EMERG;
119         else
120                 level = PR_ERR;
121 
122 	if (version == IBM_SECUREBOOT_V1 ||
123 	    version == IBM_SECUREBOOT_SOFTROM) {
124 
125 		hash_algo = dt_prop_get(node, "hash-algo");
126 		if (strcmp(hash_algo, "sha512")) {
127 			/**
128 			 * @fwts-label HashAlgoInvalid
129 			 * @fwts-advice Hash algorithm invalid, secureboot
130 			 * containers version 1 requires sha512. If you're
131 			 * running the latest POWER firmware, so probably there
132 			 * is a bug in the device tree received from hostboot.
133 			 */
134 			prlog(level, "secureboot init FAILED, hash-algo=%s "
135 			      "not supported\n", hash_algo);
136 			secureboot_enforce();
137 		}
138 		hw_key_hash_size = SHA512_DIGEST_LENGTH;
139 
140 	} else if (version == IBM_SECUREBOOT_V2) {
141 
142 		hw_key_hash_size = dt_prop_get_u32(node, "hw-key-hash-size");
143 		if (hw_key_hash_size == 0) {
144 			prlog(level, "hw-key-hash-size=%zd too short\n",
145 			      hw_key_hash_size);
146 			secureboot_enforce();
147 		}
148 		if (hw_key_hash_size > SHA512_DIGEST_LENGTH) {
149 			prlog(level, "hw-key-hash-size=%zd too big\n",
150 			      hw_key_hash_size);
151 			secureboot_enforce();
152 		}
153 
154 	} else {
155 		prlog(level, "%s FAILED. /ibm,secureboot not supported",
156 		      __func__);
157 		secureboot_enforce();
158 	}
159 
160 	hw_key_hash = dt_prop_get_def_size(node, "hw-key-hash", NULL, &size);
161 	if (!hw_key_hash) {
162 		prlog(level, "hw-key-hash not found\n");
163 		secureboot_enforce();
164 	}
165 	if (size != hw_key_hash_size) {
166 	       prlog(level, "hw_key-hash wrong size %zd (expected=%zd)\n",
167 		     size, hw_key_hash_size);
168 	       secureboot_enforce();
169 	}
170 	if (cvc_init())
171 		secureboot_enforce();
172 
173 	secure_init = true;
174 }
175 
secureboot_verify(enum resource_id id,void * buf,size_t len)176 int secureboot_verify(enum resource_id id, void *buf, size_t len)
177 {
178 	const char *name;
179 	uint64_t log;
180 	int rc = -1;
181 
182 	name = flash_map_resource_name(id);
183 	if (!name) {
184 		prlog(level, "container NOT VERIFIED, resource_id=%d "
185 		      "unknown\n", id);
186 		secureboot_enforce();
187 		return -1;
188 	}
189 
190         if (!secure_init) {
191                 prlog(level, "container NOT VERIFIED, resource_id=%d "
192                       "secureboot not yet initialized\n", id);
193 		secureboot_enforce();
194 		return -1;
195         }
196 
197 	rc = call_cvc_verify(buf, len, hw_key_hash, hw_key_hash_size, &log);
198 
199 	if (rc == OPAL_SUCCESS) {
200 		prlog(PR_NOTICE, "%s verified\n", name);
201 	} else if (rc == OPAL_PARTIAL) {
202 		/*
203 		 * The value returned in log indicates what checking has
204 		 * failed. Return codes defined in
205 		 * /hostboot/src/include/securerom/status_codes.H
206 		 */
207 		prlog(level, "%s verification FAILED. log=0x%" PRIx64 "\n",
208 			name, be64_to_cpu(log));
209 		secureboot_enforce();
210 	} else if (rc == OPAL_PARAMETER) {
211 		prlog(level, "%s NOT VERIFIED, invalid param. buf=%p, "
212 		      "len=%zd key-hash=%p hash-size=%zd\n", name, buf, len,
213 		      hw_key_hash, hw_key_hash_size);
214 		secureboot_enforce();
215 	} else if (rc == OPAL_UNSUPPORTED) {
216 		prlog(level, "%s NOT VERIFIED, CVC-verify service not "
217 		      "supported\n", name);
218 		secureboot_enforce();
219 	} else {
220 		prlog(level, "%s NOT VERIFIED, unknown CVC-verify error. "
221 		      "rc=%d\n", name, rc);
222 		secureboot_enforce();
223 	}
224 	return 0;
225 }
226