summaryrefslogtreecommitdiff
path: root/host/lib/host_signature2.c
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/host_signature2.c')
-rw-r--r--host/lib/host_signature2.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/host/lib/host_signature2.c b/host/lib/host_signature2.c
new file mode 100644
index 00000000..e07f3d06
--- /dev/null
+++ b/host/lib/host_signature2.c
@@ -0,0 +1,135 @@
+/* Copyright (c) 2011 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.
+ *
+ * Host functions for signature generation.
+ */
+
+#include <openssl/rsa.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "2sysincludes.h"
+
+#include "2common.h"
+#include "2rsa.h"
+#include "2sha.h"
+#include "cryptolib.h"
+#include "file_keys.h"
+#include "host_common.h"
+#include "host_key2.h"
+#include "host_signature2.h"
+#include "vb2_common.h"
+#include "vboot_common.h"
+
+struct vb2_signature *vb2_alloc_signature(uint32_t sig_size,
+ uint32_t data_size)
+{
+ struct vb2_signature *sig = (struct vb2_signature *)
+ calloc(sizeof(*sig) + sig_size, 1);
+ if (!sig)
+ return NULL;
+
+ sig->sig_offset = sizeof(*sig);
+ sig->sig_size = sig_size;
+ sig->data_size = data_size;
+
+ return sig;
+}
+
+void vb2_init_signature(struct vb2_signature *sig, uint8_t *sig_data,
+ uint32_t sig_size, uint32_t data_size)
+{
+ sig->sig_offset = OffsetOf(sig, sig_data);
+ sig->sig_size = sig_size;
+ sig->data_size = data_size;
+}
+
+int vb2_copy_signature(struct vb2_signature *dest,
+ const struct vb2_signature *src)
+{
+ if (dest->sig_size < src->sig_size)
+ return VB2_ERROR_SIG_SIZE;
+
+ dest->sig_size = src->sig_size;
+ dest->data_size = src->data_size;
+
+ memcpy(vb2_signature_data(dest),
+ vb2_signature_data((struct vb2_signature *)src),
+ src->sig_size);
+
+ return VB2_SUCCESS;
+}
+
+struct vb2_signature *vb2_sha512_signature(const uint8_t *data, uint32_t size)
+{
+ uint8_t digest[VB2_SHA512_DIGEST_SIZE];
+ if (VB2_SUCCESS != vb2_digest_buffer(data, size, VB2_HASH_SHA512,
+ digest, sizeof(digest)))
+ return NULL;
+
+ struct vb2_signature *sig =
+ vb2_alloc_signature(VB2_SHA512_DIGEST_SIZE, size);
+ if (!sig)
+ return NULL;
+
+ memcpy(vb2_signature_data(sig), digest, VB2_SHA512_DIGEST_SIZE);
+ return sig;
+}
+
+struct vb2_signature *vb2_calculate_signature(
+ const uint8_t *data, uint32_t size,
+ const struct vb2_private_key *key)
+{
+ uint8_t digest[VB2_MAX_DIGEST_SIZE];
+ uint32_t digest_size = vb2_digest_size(key->hash_alg);
+
+ uint32_t digest_info_size = 0;
+ const uint8_t *digest_info = NULL;
+ if (VB2_SUCCESS != vb2_digest_info(key->hash_alg,
+ &digest_info, &digest_info_size))
+ return NULL;
+
+ /* Calculate the digest */
+ if (VB2_SUCCESS != vb2_digest_buffer(data, size, key->hash_alg,
+ digest, digest_size))
+ return NULL;
+
+ /* Prepend the digest info to the digest */
+ int signature_digest_len = digest_size + digest_info_size;
+ uint8_t *signature_digest = malloc(signature_digest_len);
+ if (!signature_digest)
+ return NULL;
+
+ memcpy(signature_digest, digest_info, digest_info_size);
+ memcpy(signature_digest + digest_info_size, digest, digest_size);
+
+ /* Allocate output signature */
+ struct vb2_signature *sig = (struct vb2_signature *)
+ vb2_alloc_signature(vb2_rsa_sig_size(key->sig_alg), size);
+ if (!sig) {
+ free(signature_digest);
+ return NULL;
+ }
+
+ /* Sign the signature_digest into our output buffer */
+ int rv = RSA_private_encrypt(signature_digest_len, /* Input length */
+ signature_digest, /* Input data */
+ vb2_signature_data(sig), /* Output sig */
+ key->rsa_private_key, /* Key to use */
+ RSA_PKCS1_PADDING); /* Padding */
+ free(signature_digest);
+
+ if (-1 == rv) {
+ VB2_DEBUG("%s: RSA_private_encrypt() failed.\n", __func__);
+ free(sig);
+ return NULL;
+ }
+
+ /* Return the signature */
+ return sig;
+}