[coreboot-gerrit] Change in coreboot[master]: security/crypto: Add common code and errors

Philipp Deppenwiese (Code Review) gerrit at coreboot.org
Thu Jan 11 15:11:07 CET 2018


Philipp Deppenwiese has uploaded this change for review. ( https://review.coreboot.org/23217


Change subject: security/crypto: Add common code and errors
......................................................................

security/crypto: Add common code and errors

* Add common code for workbuffers.
* Add common code for alignment and safe memcmp.
* Add error enumeration.
* Integrated code from 3rdparty/vboot.

Change-Id: I38441349b46dc142993fd351878847fdd814bae6
Signed-off-by: Philipp Deppenwiese <zaolin at das-labor.org>
---
A src/security/crypto/common.h
A src/security/crypto/common/common.c
A src/security/crypto/errors.h
3 files changed, 304 insertions(+), 0 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/17/23217/1

diff --git a/src/security/crypto/common.h b/src/security/crypto/common.h
new file mode 100644
index 0000000..8a1bfd1
--- /dev/null
+++ b/src/security/crypto/common.h
@@ -0,0 +1,110 @@
+/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Common functions between firmware and kernel verified boot.
+ */
+
+#ifndef CRYPTO_COMMON_H_
+#define CRYPTO_COMMON_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/* We might get away with using __alignof__(void *), but since GCC defines a
+ * macro for us we'll be safe and use that. */
+#define WORKBUF_ALIGN __BIGGEST_ALIGNMENT__
+
+/* Work buffer */
+struct workbuf {
+	uint8_t *buf;
+	uint32_t size;
+};
+
+/**
+ * Safer memcmp() for use in crypto.
+ *
+ * Compares the buffers to see if they are equal.  Time taken to perform
+ * the comparison is dependent only on the size, not the relationship of
+ * the match between the buffers.  Note that unlike memcmp(), this only
+ * indicates inequality, not which buffer is lesser.
+ *
+ * @param s1		First buffer
+ * @param s2		Second buffer
+ * @param size		Number of bytes to compare
+ * @return 0 if match or size=0, non-zero if at least one byte mismatched.
+ */
+int safe_memcmp(const void *s1, const void *s2, size_t size);
+
+/**
+ * Align a buffer and check its size.
+ *
+ * @param **ptr		Pointer to pointer to align
+ * @param *size		Points to size of buffer pointed to by *ptr
+ * @param align		Required alignment (must be power of 2)
+ * @param want_size	Required size
+ * @return SUCCESS, or non-zero if error.
+ */
+int align(uint8_t **ptr,
+	      uint32_t *size,
+	      uint32_t align,
+	      uint32_t want_size);
+
+/**
+ * Initialize a work buffer.
+ *
+ * @param wb		Work buffer to init
+ * @param buf		Pointer to work buffer data
+ * @param size		Size of work buffer data in bytes
+ */
+void workbuf_init(struct workbuf *wb, uint8_t *buf, uint32_t size);
+
+/**
+ * Allocate space in a work buffer.
+ *
+ * Note that the returned buffer will always be aligned to WORKBUF_ALIGN.
+ *
+ * The work buffer acts like a stack, and detailed tracking of allocs and frees
+ * is not done.  The caller must track the size of each allocation and free via
+ * workbuf_free() in the reverse order they were allocated.
+ *
+ * An acceptable alternate workflow inside a function is to pass in a const
+ * work buffer, then make a local copy.  Allocations done to the local copy
+ * then don't change the passed-in work buffer, and will effectively be freed
+ * when the local copy goes out of scope.
+ *
+ * @param wb		Work buffer
+ * @param size		Requested size in bytes
+ * @return A pointer to the allocated space, or NULL if error.
+ */
+void *workbuf_alloc(struct workbuf *wb, uint32_t size);
+
+/**
+ * Reallocate space in a work buffer.
+ *
+ * Note that the returned buffer will always be aligned to WORKBUF_ALIGN.
+ * The work buffer acts like a stack, so this must only be done to the most
+ * recently allocated buffer.
+ *
+ * @param wb		Work buffer
+ * @param oldsize	Old allocation size in bytes
+ * @param newsize	Requested size in bytes
+ * @return A pointer to the allocated space, or NULL if error.
+ */
+void *workbuf_realloc(struct workbuf *wb,
+			  uint32_t oldsize,
+			  uint32_t newsize);
+
+/**
+ * Free the preceding allocation.
+ *
+ * Note that the work buffer acts like a stack, and detailed tracking of
+ * allocs and frees is not done.  The caller must track the size of each
+ * allocation and free them in reverse order.
+ *
+ * @param wb		Work buffer
+ * @param size		Size of data to free
+ */
+void workbuf_free(struct workbuf *wb, uint32_t size);
+
+#endif  /* CRYPTO_COMMON_H_ */
diff --git a/src/security/crypto/common/common.c b/src/security/crypto/common/common.c
new file mode 100644
index 0000000..80652ad
--- /dev/null
+++ b/src/security/crypto/common/common.c
@@ -0,0 +1,109 @@
+/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Common functions between firmware and kernel verified boot.
+ * (Firmware portion)
+ */
+
+#include <security/crypto/common.h>
+#include <security/crypto/errors.h>
+
+int safe_memcmp(const void *s1, const void *s2, size_t size)
+{
+	const unsigned char *us1 = s1;
+	const unsigned char *us2 = s2;
+	int result = 0;
+
+	if (0 == size)
+		return 0;
+
+	/*
+	 * Code snippet without data-dependent branch due to Nate Lawson
+	 * (nate at root.org) of Root Labs.
+	 */
+	while (size--)
+		result |= *us1++ ^ *us2++;
+
+	return result != 0;
+}
+
+int align(uint8_t **ptr, uint32_t *size, uint32_t align, uint32_t want_size)
+{
+	uintptr_t p = (uintptr_t)*ptr;
+	uintptr_t offs = p & (align - 1);
+
+	if (offs) {
+		offs = align - offs;
+
+		if (*size < offs)
+			return ERROR_UNKNOWN;
+
+		*ptr += offs;
+		*size -= offs;
+	}
+
+	if (*size < want_size)
+		return ERROR_UNKNOWN;
+
+	return SUCCESS;
+}
+
+void workbuf_init(struct workbuf *wb, uint8_t *buf, uint32_t size)
+{
+	wb->buf = buf;
+	wb->size = size;
+
+	/* Align the buffer so allocations will be aligned */
+	if (align(&wb->buf, &wb->size, WORKBUF_ALIGN, 0))
+		wb->size = 0;
+}
+
+/**
+ * Round up a number to a multiple of WORKBUF_ALIGN
+ *
+ * @param v		Number to round up
+ * @return The number, rounded up.
+ */
+static __inline uint32_t wb_round_up(uint32_t v)
+{
+	return (v + WORKBUF_ALIGN - 1) & ~(WORKBUF_ALIGN - 1);
+}
+
+void *workbuf_alloc(struct workbuf *wb, uint32_t size)
+{
+	uint8_t *ptr = wb->buf;
+
+	/* Round up size to work buffer alignment */
+	size = wb_round_up(size);
+
+	if (size > wb->size)
+		return NULL;
+
+	wb->buf += size;
+	wb->size -= size;
+
+	return ptr;
+}
+
+void *workbuf_realloc(struct workbuf *wb,
+			  uint32_t oldsize,
+			  uint32_t newsize)
+{
+	/*
+	 * Just free and allocate to update the size.  No need to move/copy
+	 * memory, since the new pointer is guaranteed to be the same as the
+	 * old one.  The new allocation can fail, if the new size is too big.
+	 */
+	workbuf_free(wb, oldsize);
+	return workbuf_alloc(wb, newsize);
+}
+
+void workbuf_free(struct workbuf *wb, uint32_t size)
+{
+	/* Round up size to work buffer alignment */
+	size = wb_round_up(size);
+
+	wb->buf -= size;
+	wb->size += size;
+}
diff --git a/src/security/crypto/errors.h b/src/security/crypto/errors.h
new file mode 100644
index 0000000..c8fad50
--- /dev/null
+++ b/src/security/crypto/errors.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef CRYPTO_ERRORS_H_
+#define CRYPTO_ERRORS_H_
+
+/*
+ * Return codes from verified boot functions.
+ *
+ * Note that other values may be passed through from vb2ex_*() calls; see
+ * the comment for ERROR_EX below.
+ */
+enum return_code {
+	/* Success - no error */
+	SUCCESS = 0,
+
+	/*
+	 * All vboot2 error codes start at a large offset from zero, to reduce
+	 * the risk of overlap with other error codes (TPM, etc.).
+	 */
+	ERROR_BASE = 0x10000000,
+
+	/* Unknown / unspecified error */
+	ERROR_UNKNOWN = ERROR_BASE + 1,
+
+	/* Mock error for testing */
+	ERROR_MOCK,
+
+        /**********************************************************************
+	 * SHA errors
+	 */
+	ERROR_SHA = ERROR_BASE + 0x010000,
+
+	/* Bad algorithm in digest_init() */
+	ERROR_SHA_INIT_ALGORITHM,
+
+	/* Bad algorithm in digest_extend() */
+	ERROR_SHA_EXTEND_ALGORITHM,
+
+	/* Bad algorithm in digest_finalize() */
+	ERROR_SHA_FINALIZE_ALGORITHM,
+
+	/* Digest size buffer too small in digest_finalize() */
+	ERROR_SHA_FINALIZE_DIGEST_SIZE,
+
+        /**********************************************************************
+	 * RSA errors
+	 */
+	ERROR_RSA = ERROR_BASE + 0x020000,
+
+	/* Padding mismatch in check_padding() */
+	ERROR_RSA_PADDING,
+
+	/* Bad algorithm in check_padding() */
+	ERROR_RSA_PADDING_ALGORITHM,
+
+	/* Null param passed to verify_digest() */
+	ERROR_RSA_VERIFY_PARAM,
+
+	/* Bad algorithm in verify_digest() */
+	ERROR_RSA_VERIFY_ALGORITHM,
+
+	/* Bad signature length in verify_digest() */
+	ERROR_RSA_VERIFY_SIG_LEN,
+
+	/* Work buffer too small in verify_digest() */
+	ERROR_RSA_VERIFY_WORKBUF,
+
+	/* Digest mismatch in verify_digest() */
+	ERROR_RSA_VERIFY_DIGEST,
+
+	/* Bad size calculation in check_padding() */
+	ERROR_RSA_PADDING_SIZE,
+
+        /**********************************************************************
+	 * Highest non-zero error generated inside vboot library.  Note that
+	 * error codes passed through vboot when it calls external APIs may
+	 * still be outside this range.
+	 */
+	ERROR_MAX = ERROR_BASE + 0x1fffffff,
+};
+
+#endif  /* CRYPTO_ERRORS_H_ */

-- 
To view, visit https://review.coreboot.org/23217
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I38441349b46dc142993fd351878847fdd814bae6
Gerrit-Change-Number: 23217
Gerrit-PatchSet: 1
Gerrit-Owner: Philipp Deppenwiese <zaolin.daisuki at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180111/7aae0f4a/attachment-0001.html>


More information about the coreboot-gerrit mailing list