nvm.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /* Copyright 2016 The Chromium OS Authors. All rights reserved.
  2. * Use of this source code is governed by a BSD-style license that can be
  3. * found in the LICENSE file.
  4. */
  5. #include "2sysincludes.h"
  6. #include "2hmac.h"
  7. #include "2sha.h"
  8. #include "bdb_api.h"
  9. #include "bdb_struct.h"
  10. #include "bdb.h"
  11. #include "nvm.h"
  12. #include "secrets.h"
  13. static int nvmrw_validate(const void *buf, uint32_t size)
  14. {
  15. const struct nvmrw *nvm = buf;
  16. if (nvm->struct_magic != NVM_RW_MAGIC)
  17. return BDB_ERROR_NVM_RW_MAGIC;
  18. if (nvm->struct_major_version != NVM_HEADER_VERSION_MAJOR)
  19. return BDB_ERROR_NVM_STRUCT_VERSION;
  20. if (size < nvm->struct_size)
  21. return BDB_ERROR_NVM_STRUCT_SIZE;
  22. /*
  23. * We allow any sizes between min and max so that we can handle minor
  24. * version mismatches. Reader can be older than data or the other way
  25. * around. FW in slot B can upgrade NVM-RW but fails to qualify as a
  26. * stable boot path. Then, FW in slot A is invoked which is older than
  27. * the NVM-RW written by FW in slot B.
  28. */
  29. if (nvm->struct_size < NVM_RW_MIN_STRUCT_SIZE ||
  30. NVM_RW_MAX_STRUCT_SIZE < nvm->struct_size)
  31. return BDB_ERROR_NVM_STRUCT_SIZE;
  32. return BDB_SUCCESS;
  33. }
  34. static int nvmrw_verify(const struct bdb_secrets *secrets,
  35. const struct nvmrw *nvm, uint32_t size)
  36. {
  37. uint8_t mac[NVM_HMAC_SIZE];
  38. int rv;
  39. if (!secrets || !nvm)
  40. return BDB_ERROR_NVM_INVALID_PARAMETER;
  41. rv = nvmrw_validate(nvm, size);
  42. if (rv)
  43. return rv;
  44. /* Compute and verify HMAC */
  45. if (hmac(VB2_HASH_SHA256, secrets->nvm_rw, BDB_SECRET_SIZE,
  46. nvm, nvm->struct_size - sizeof(mac), mac, sizeof(mac)))
  47. return BDB_ERROR_NVM_RW_HMAC;
  48. /* TODO: Use safe_memcmp */
  49. if (memcmp(mac, nvm->hmac, sizeof(mac)))
  50. return BDB_ERROR_NVM_RW_INVALID_HMAC;
  51. return BDB_SUCCESS;
  52. }
  53. int nvmrw_write(struct vba_context *ctx, enum nvm_type type)
  54. {
  55. struct nvmrw *nvm = &ctx->nvmrw;
  56. int retry = NVM_MAX_WRITE_RETRY;
  57. int rv;
  58. if (!ctx)
  59. return BDB_ERROR_NVM_INVALID_PARAMETER;
  60. if (!ctx->secrets)
  61. return BDB_ERROR_NVM_INVALID_SECRET;
  62. rv = nvmrw_validate(nvm, sizeof(*nvm));
  63. if (rv)
  64. return rv;
  65. /* Update HMAC */
  66. hmac(VB2_HASH_SHA256, ctx->secrets->nvm_rw, BDB_SECRET_SIZE,
  67. nvm, nvm->struct_size - sizeof(nvm->hmac),
  68. nvm->hmac, sizeof(nvm->hmac));
  69. while (retry--) {
  70. uint8_t buf[sizeof(struct nvmrw)];
  71. if (vbe_write_nvm(type, nvm, nvm->struct_size))
  72. continue;
  73. if (vbe_read_nvm(type, buf, sizeof(buf)))
  74. continue;
  75. if (memcmp(buf, nvm, sizeof(buf)))
  76. continue;
  77. /* Write success */
  78. return BDB_SUCCESS;
  79. }
  80. /* NVM seems corrupted. Go to chip recovery mode */
  81. return BDB_ERROR_NVM_WRITE;
  82. }
  83. static int read_verify_nvmrw(enum nvm_type type,
  84. const struct bdb_secrets *secrets,
  85. uint8_t *buf, uint32_t buf_size)
  86. {
  87. struct nvmrw *nvm = (struct nvmrw *)buf;
  88. int rv;
  89. /* Read minimum amount */
  90. if (vbe_read_nvm(type, buf, NVM_MIN_STRUCT_SIZE))
  91. return BDB_ERROR_NVM_VBE_READ;
  92. /* Validate the content */
  93. rv = nvmrw_validate(buf, buf_size);
  94. if (rv)
  95. return rv;
  96. /* Read full body */
  97. if (vbe_read_nvm(type, buf, nvm->struct_size))
  98. return BDB_ERROR_NVM_VBE_READ;
  99. /* Verify the content */
  100. rv = nvmrw_verify(secrets, nvm, sizeof(*nvm));
  101. return rv;
  102. return BDB_SUCCESS;
  103. }
  104. int nvmrw_read(struct vba_context *ctx)
  105. {
  106. uint8_t buf1[NVM_RW_MAX_STRUCT_SIZE];
  107. uint8_t buf2[NVM_RW_MAX_STRUCT_SIZE];
  108. struct nvmrw *nvm1 = (struct nvmrw *)buf1;
  109. struct nvmrw *nvm2 = (struct nvmrw *)buf2;
  110. int rv1, rv2;
  111. /* Read and verify the 1st copy */
  112. rv1 = read_verify_nvmrw(NVM_TYPE_RW_PRIMARY, ctx->secrets,
  113. buf1, sizeof(buf1));
  114. /* Read and verify the 2nd copy */
  115. rv2 = read_verify_nvmrw(NVM_TYPE_RW_SECONDARY, ctx->secrets,
  116. buf2, sizeof(buf2));
  117. if (rv1 == BDB_SUCCESS && rv2 == BDB_SUCCESS) {
  118. /* Sync primary and secondary based on update_count. */
  119. if (nvm1->update_count > nvm2->update_count)
  120. rv2 = !BDB_SUCCESS;
  121. else if (nvm1->update_count < nvm2->update_count)
  122. rv1 = !BDB_SUCCESS;
  123. } else if (rv1 != BDB_SUCCESS && rv2 != BDB_SUCCESS){
  124. /* Abort. Neither was successful. */
  125. return rv1;
  126. }
  127. if (rv1 == BDB_SUCCESS)
  128. /* both copies are good. use primary copy */
  129. memcpy(&ctx->nvmrw, buf1, sizeof(ctx->nvmrw));
  130. else
  131. /* primary is bad but secondary is good. */
  132. memcpy(&ctx->nvmrw, buf2, sizeof(ctx->nvmrw));
  133. if (ctx->nvmrw.struct_minor_version != NVM_HEADER_VERSION_MINOR) {
  134. /*
  135. * Upgrade or downgrade is required. So, we need to write both.
  136. * When upgrading, this is the place where new fields should be
  137. * initialized. We don't increment update_count.
  138. */
  139. ctx->nvmrw.struct_minor_version = NVM_HEADER_VERSION_MINOR;
  140. ctx->nvmrw.struct_size = sizeof(ctx->nvmrw);
  141. /* We don't worry about calculating hmac twice because
  142. * this is a corner case. */
  143. rv1 = nvmrw_write(ctx, NVM_TYPE_RW_PRIMARY);
  144. rv2 = nvmrw_write(ctx, NVM_TYPE_RW_SECONDARY);
  145. } else if (rv1 != BDB_SUCCESS) {
  146. /* primary copy is bad. sync it with secondary copy */
  147. rv1 = nvmrw_write(ctx, NVM_TYPE_RW_PRIMARY);
  148. } else if (rv2 != BDB_SUCCESS){
  149. /* secondary copy is bad. sync it with primary copy */
  150. rv2 = nvmrw_write(ctx, NVM_TYPE_RW_SECONDARY);
  151. } else {
  152. /* Both copies are good and versions are same as the reader.
  153. * Skip writing. This should be the common case. */
  154. }
  155. if (rv1 || rv2)
  156. return rv1 ? rv1 : rv2;
  157. return BDB_SUCCESS;
  158. }
  159. static int nvmrw_init(struct vba_context *ctx)
  160. {
  161. if (nvmrw_read(ctx))
  162. return BDB_ERROR_NVM_INIT;
  163. return BDB_SUCCESS;
  164. }
  165. int vba_update_kernel_version(struct vba_context *ctx,
  166. uint32_t kernel_data_key_version,
  167. uint32_t kernel_version)
  168. {
  169. struct nvmrw *nvm = &ctx->nvmrw;
  170. if (nvmrw_verify(ctx->secrets, nvm, sizeof(*nvm))) {
  171. if (nvmrw_init(ctx))
  172. return BDB_ERROR_NVM_INIT;
  173. }
  174. if (nvm->min_kernel_data_key_version < kernel_data_key_version ||
  175. nvm->min_kernel_version < kernel_version) {
  176. int rv1, rv2;
  177. /* Roll forward versions */
  178. nvm->min_kernel_data_key_version = kernel_data_key_version;
  179. nvm->min_kernel_version = kernel_version;
  180. /* Increment update counter */
  181. nvm->update_count++;
  182. /* Update both copies */
  183. rv1 = nvmrw_write(ctx, NVM_TYPE_RW_PRIMARY);
  184. rv2 = nvmrw_write(ctx, NVM_TYPE_RW_SECONDARY);
  185. if (rv1 || rv2)
  186. return BDB_ERROR_RECOVERY_REQUEST;
  187. }
  188. return BDB_SUCCESS;
  189. }
  190. int vba_update_buc(struct vba_context *ctx, uint8_t *new_buc)
  191. {
  192. struct nvmrw *nvm = &ctx->nvmrw;
  193. uint8_t buc[BUC_ENC_DIGEST_SIZE];
  194. int rv1, rv2;
  195. if (nvmrw_verify(ctx->secrets, nvm, sizeof(*nvm))) {
  196. if (nvmrw_init(ctx))
  197. return BDB_ERROR_NVM_INIT;
  198. }
  199. /* Encrypt new BUC
  200. * Note that we do not need to decide whether we should use hardware
  201. * crypto or not because this is supposed to be running in RW code. */
  202. if (vbe_aes256_encrypt(new_buc, BUC_ENC_DIGEST_SIZE,
  203. ctx->secrets->buc, buc))
  204. return BDB_ERROR_ENCRYPT_BUC;
  205. /* Return if new BUC is same as current one. */
  206. if (!memcmp(buc, nvm->buc_enc_digest, sizeof(buc)))
  207. return BDB_SUCCESS;
  208. memcpy(nvm->buc_enc_digest, buc, sizeof(buc));
  209. /* Increment update counter */
  210. nvm->update_count++;
  211. /* Write new BUC */
  212. rv1 = nvmrw_write(ctx, NVM_TYPE_RW_PRIMARY);
  213. rv2 = nvmrw_write(ctx, NVM_TYPE_RW_SECONDARY);
  214. if (rv1 || rv2)
  215. return BDB_ERROR_WRITE_BUC;
  216. return BDB_SUCCESS;
  217. }
  218. int nvmrw_get(struct vba_context *ctx, enum nvmrw_var var, uint32_t *val)
  219. {
  220. struct nvmrw *nvm = &ctx->nvmrw;
  221. /* No init or verify so that this can be called from futility.
  222. * Callers are responsible for init and verify. */
  223. switch (var) {
  224. case NVMRW_VAR_UPDATE_COUNT:
  225. *val = nvm->update_count;
  226. break;
  227. case NVMRW_VAR_MIN_KERNEL_DATA_KEY_VERSION:
  228. *val = nvm->min_kernel_data_key_version;
  229. break;
  230. case NVMRW_VAR_MIN_KERNEL_VERSION:
  231. *val = nvm->min_kernel_version;
  232. break;
  233. case NVMRW_VAR_BUC_TYPE:
  234. *val = nvm->buc_type;
  235. break;
  236. case NVMRW_VAR_FLAG_BUC_PRESENT:
  237. *val = nvm->flags & NVM_RW_FLAG_BUC_PRESENT;
  238. break;
  239. case NVMRW_VAR_FLAG_DFM_DISABLE:
  240. *val = nvm->flags & NVM_RW_FLAG_DFM_DISABLE;
  241. break;
  242. case NVMRW_VAR_FLAG_DOSM:
  243. *val = nvm->flags & NVM_RW_FLAG_DOSM;
  244. break;
  245. default:
  246. return BDB_ERROR_NVM_INVALID_PARAMETER;
  247. }
  248. return BDB_SUCCESS;
  249. }
  250. #define MAX_8BIT_UINT ((((uint64_t)1) << 8) - 1)
  251. int nvmrw_set(struct vba_context *ctx, enum nvmrw_var var, uint32_t val)
  252. {
  253. struct nvmrw *nvm = &ctx->nvmrw;
  254. /* No init or verify so that this can be called from futility.
  255. * Callers are responsible for init and verify. */
  256. switch (var) {
  257. case NVMRW_VAR_UPDATE_COUNT:
  258. nvm->update_count = val;
  259. break;
  260. case NVMRW_VAR_MIN_KERNEL_DATA_KEY_VERSION:
  261. nvm->min_kernel_data_key_version = val;
  262. break;
  263. case NVMRW_VAR_MIN_KERNEL_VERSION:
  264. nvm->min_kernel_version = val;
  265. break;
  266. case NVMRW_VAR_BUC_TYPE:
  267. if (val > MAX_8BIT_UINT)
  268. return BDB_ERROR_NVM_INVALID_PARAMETER;
  269. nvm->buc_type = val;
  270. break;
  271. case NVMRW_VAR_FLAG_BUC_PRESENT:
  272. nvm->flags &= ~NVM_RW_FLAG_BUC_PRESENT;
  273. nvm->flags |= val ? NVM_RW_FLAG_BUC_PRESENT : 0;
  274. break;
  275. case NVMRW_VAR_FLAG_DFM_DISABLE:
  276. nvm->flags &= ~NVM_RW_FLAG_DFM_DISABLE;
  277. nvm->flags |= val ? NVM_RW_FLAG_DFM_DISABLE : 0;
  278. break;
  279. case NVMRW_VAR_FLAG_DOSM:
  280. nvm->flags &= ~NVM_RW_FLAG_DOSM;
  281. nvm->flags |= val ? NVM_RW_FLAG_DOSM : 0;
  282. break;
  283. default:
  284. return BDB_ERROR_NVM_INVALID_PARAMETER;
  285. }
  286. return BDB_SUCCESS;
  287. }