bdb: Add vba_update_buc
authorDaisuke Nojiri <dnojiri@chromium.org>
Fri, 6 May 2016 19:32:38 +0000 (12:32 -0700)
committerchrome-bot <chrome-bot@chromium.org>
Thu, 23 Jun 2016 03:01:58 +0000 (20:01 -0700)
vba_update_buc writes a BUC (boot unlock code) to NVM-RW. It will be called
by AP-RW to update a BUC.

BUG=chrome-os-partner:51907
BRANCH=tot
TEST=make runtests

Change-Id: Ic91f34b60b11ebce948bce01993ddb44519a59b8
Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/346233

firmware/bdb/bdb.h
firmware/bdb/bdb_api.h
firmware/bdb/nvm.c
firmware/bdb/stub.c
tests/bdb_sprw_test.c

index 9f3b9c6..5163401 100644 (file)
@@ -88,6 +88,9 @@ enum bdb_return_code {
        BDB_ERROR_NVM_STRUCT_VERSION,
        BDB_ERROR_NVM_VBE_READ,
        BDB_ERROR_NVM_RW_BUFFER_SMALL,
+       BDB_ERROR_DECRYPT_BUC,
+       BDB_ERROR_ENCRYPT_BUC,
+       BDB_ERROR_WRITE_BUC,
 };
 
 /*****************************************************************************/
index 9979824..7ef935c 100644 (file)
@@ -68,6 +68,15 @@ int vba_update_kernel_version(struct vba_context *ctx,
                              uint32_t kernel_version);
 
 /**
+ * Write new boot unlock code to NVM-RW
+ *
+ * @param ctx
+ * @param new_buc      New BUC to be written
+ * @return             BDB_SUCCESS or BDB_ERROR_*
+ */
+int vba_update_buc(struct vba_context *ctx, uint8_t *new_buc);
+
+/**
  * Get vboot register value
  *
  * Implemented by each chip
@@ -119,4 +128,28 @@ int vbe_read_nvm(enum nvm_type type, uint8_t *buf, uint32_t size);
  */
 int vbe_write_nvm(enum nvm_type type, void *buf, uint32_t size);
 
+/**
+ * Encrypt data by AES-256
+ *
+ * @param msg  Message to be encrypted
+ * @param len  Length of <msg> in bytes
+ * @param key  Key used for encryption
+ * @param out  Buffer where encrypted message is stored
+ * @return     BDB_SUCCESS or BDB_ERROR_*
+ */
+int vbe_aes256_encrypt(const uint8_t *msg, uint32_t len, const uint8_t *key,
+                      uint8_t *out);
+
+/**
+ * Decrypt data by AES-256
+ *
+ * @param msg  Message to be decrypted
+ * @param len  Length of <msg> in bytes
+ * @param key  Key used for decryption
+ * @param out  Buffer where decrypted message is stored
+ * @return     BDB_SUCCESS or BDB_ERROR_*
+ */
+int vbe_aes256_decrypt(const uint8_t *msg, uint32_t len, const uint8_t *key,
+                      uint8_t *out);
+
 #endif
index b5c53af..a7c56b0 100644 (file)
@@ -229,3 +229,39 @@ int vba_update_kernel_version(struct vba_context *ctx,
 
        return BDB_SUCCESS;
 }
+
+int vba_update_buc(struct vba_context *ctx, uint8_t *new_buc)
+{
+       struct nvmrw *nvm = &ctx->nvmrw;
+       uint8_t buc[BUC_ENC_DIGEST_SIZE];
+       int rv1, rv2;
+
+       if (nvmrw_verify(ctx->ro_secrets, nvm, sizeof(*nvm))) {
+               if (nvmrw_init(ctx))
+                       return BDB_ERROR_NVM_INIT;
+       }
+
+       /* Encrypt new BUC
+        * Note that we do not need to decide whether we should use hardware
+        * crypto or not because this is supposed to be running in RW code. */
+       if (vbe_aes256_encrypt(new_buc, BUC_ENC_DIGEST_SIZE,
+                              ctx->rw_secrets->buc, buc))
+               return BDB_ERROR_ENCRYPT_BUC;
+
+       /* Return if new BUC is same as current one. */
+       if (!memcmp(buc, nvm->buc_enc_digest, sizeof(buc)))
+               return BDB_SUCCESS;
+
+       memcpy(nvm->buc_enc_digest, buc, sizeof(buc));
+
+       /* Increment update counter */
+       nvm->update_count++;
+
+       /* Write new BUC */
+       rv1 = nvmrw_write(ctx, NVM_TYPE_RW_PRIMARY);
+       rv2 = nvmrw_write(ctx, NVM_TYPE_RW_SECONDARY);
+       if (rv1 || rv2)
+               return BDB_ERROR_WRITE_BUC;
+
+       return BDB_SUCCESS;
+}
index 58a0096..4af9126 100644 (file)
@@ -35,3 +35,17 @@ int vbe_write_nvm(enum nvm_type type, void *buf, uint32_t size)
 {
        return BDB_ERROR_NOT_IMPLEMENTED;
 }
+
+__attribute__((weak))
+int vbe_aes256_encrypt(const uint8_t *msg, uint32_t len, const uint8_t *key,
+                      uint8_t *out)
+{
+       return BDB_ERROR_NOT_IMPLEMENTED;
+}
+
+__attribute__((weak))
+int vbe_aes256_decrypt(const uint8_t *msg, uint32_t len, const uint8_t *key,
+                      uint8_t *out)
+{
+       return BDB_ERROR_NOT_IMPLEMENTED;
+}
index 06739ae..75deba6 100644 (file)
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <openssl/aes.h>
 
 #include "2sha.h"
 #include "2hmac.h"
@@ -34,6 +35,13 @@ struct bdb_ro_secrets secrets = {
        .nvm_rw = {0x00, },
 };
 
+struct bdb_rw_secrets rw_secrets = {
+       .buc = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff},
+};
+
 static int vbe_write_nvm_failure = 0;
 
 static struct bdb_header *create_bdb(const char *key_dir,
@@ -554,6 +562,48 @@ static void test_update_kernel_version(void)
        verify_kernel_version(0, 0, 1, 0, BDB_SUCCESS);
 }
 
+int vbe_aes256_encrypt(const uint8_t *msg, uint32_t len, const uint8_t *key,
+                      uint8_t *out)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               out[i] = msg[i] ^ key[i % 256/8];
+
+       return BDB_SUCCESS;
+}
+
+int vbe_aes256_decrypt(const uint8_t *msg, uint32_t len, const uint8_t *key,
+                      uint8_t *out)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               out[i] = msg[i] ^ key[i % 256/8];
+
+       return BDB_SUCCESS;
+}
+
+static void test_update_buc(void)
+{
+       uint8_t new_buc[BUC_ENC_DIGEST_SIZE];
+       uint8_t enc_buc[BUC_ENC_DIGEST_SIZE];
+       struct nvmrw *nvm = (struct nvmrw *)nvmrw1;
+       struct vba_context ctx = {
+               .bdb = NULL,
+               .ro_secrets = &secrets,
+               .rw_secrets = &rw_secrets,
+       };
+
+       install_nvm(NVM_TYPE_RW_PRIMARY, 0, 1, 0);
+       install_nvm(NVM_TYPE_RW_SECONDARY, 1, 0, 0);
+
+       TEST_SUCC(vba_update_buc(&ctx, new_buc), NULL);
+       vbe_aes256_encrypt(new_buc, sizeof(new_buc), ctx.rw_secrets->buc,
+                          enc_buc);
+       TEST_SUCC(memcmp(nvm->buc_enc_digest, enc_buc, sizeof(new_buc)), NULL);
+}
+
 int main(int argc, char *argv[])
 {
        if (argc != 2) {
@@ -566,6 +616,7 @@ int main(int argc, char *argv[])
        test_nvm_read();
        test_nvm_write();
        test_update_kernel_version();
+       test_update_buc();
 
        return gTestSuccess ? 0 : 255;
 }