aboutsummaryrefslogtreecommitdiff
path: root/lib/sign_digest.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sign_digest.c')
-rw-r--r--lib/sign_digest.c94
1 files changed, 85 insertions, 9 deletions
diff --git a/lib/sign_digest.c b/lib/sign_digest.c
index 9a35256..8ec0990 100644
--- a/lib/sign_digest.c
+++ b/lib/sign_digest.c
@@ -19,6 +19,10 @@
#include <openssl/pkcs7.h>
#include <string.h>
+#ifndef OPENSSL_IS_BORINGSSL
+#include <openssl/engine.h>
+#endif
+
static int print_openssl_err_cb(const char *str,
size_t len __attribute__((unused)),
void *u __attribute__((unused)))
@@ -81,6 +85,11 @@ static int read_certificate(const char *certfile, X509 **cert_ret)
X509 *cert;
int err;
+ if (!certfile) {
+ libfsverity_error_msg("no certificate specified");
+ return -EINVAL;
+ }
+
errno = 0;
bio = BIO_new_file(certfile, "r");
if (!bio) {
@@ -212,6 +221,15 @@ out:
return err;
}
+static int
+load_pkcs11_private_key(const struct libfsverity_signature_params *sig_params
+ __attribute__((unused)),
+ EVP_PKEY **pkey_ret __attribute__((unused)))
+{
+ libfsverity_error_msg("BoringSSL doesn't support PKCS#11 tokens");
+ return -EINVAL;
+}
+
#else /* OPENSSL_IS_BORINGSSL */
static BIO *new_mem_buf(const void *buf, size_t size)
@@ -315,16 +333,79 @@ out:
return err;
}
+static int
+load_pkcs11_private_key(const struct libfsverity_signature_params *sig_params,
+ EVP_PKEY **pkey_ret)
+{
+ ENGINE *engine;
+
+ if (!sig_params->pkcs11_engine) {
+ libfsverity_error_msg("no PKCS#11 engine specified");
+ return -EINVAL;
+ }
+ if (!sig_params->pkcs11_module) {
+ libfsverity_error_msg("no PKCS#11 module specified");
+ return -EINVAL;
+ }
+ ENGINE_load_dynamic();
+ engine = ENGINE_by_id("dynamic");
+ if (!engine) {
+ error_msg_openssl("failed to initialize OpenSSL PKCS#11 engine");
+ return -EINVAL;
+ }
+ if (!ENGINE_ctrl_cmd_string(engine, "SO_PATH",
+ sig_params->pkcs11_engine, 0) ||
+ !ENGINE_ctrl_cmd_string(engine, "ID", "pkcs11", 0) ||
+ !ENGINE_ctrl_cmd_string(engine, "LIST_ADD", "1", 0) ||
+ !ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0) ||
+ !ENGINE_ctrl_cmd_string(engine, "MODULE_PATH",
+ sig_params->pkcs11_module, 0) ||
+ !ENGINE_init(engine)) {
+ error_msg_openssl("failed to initialize OpenSSL PKCS#11 engine");
+ ENGINE_free(engine);
+ return -EINVAL;
+ }
+ *pkey_ret = ENGINE_load_private_key(engine, sig_params->pkcs11_keyid,
+ NULL, NULL);
+ ENGINE_finish(engine);
+ ENGINE_free(engine);
+ if (!*pkey_ret) {
+ error_msg_openssl("failed to load private key from PKCS#11 token");
+ return -EINVAL;
+ }
+ return 0;
+}
+
#endif /* !OPENSSL_IS_BORINGSSL */
+/* Get a private key, either from disk or from a PKCS#11 token. */
+static int
+get_private_key(const struct libfsverity_signature_params *sig_params,
+ EVP_PKEY **pkey_ret)
+{
+ if (sig_params->pkcs11_engine || sig_params->pkcs11_module ||
+ sig_params->pkcs11_keyid) {
+ if (sig_params->keyfile) {
+ libfsverity_error_msg("private key must be specified either by file or by PKCS#11 token, not both");
+ return -EINVAL;
+ }
+ return load_pkcs11_private_key(sig_params, pkey_ret);
+ }
+ if (!sig_params->keyfile) {
+ libfsverity_error_msg("no private key specified");
+ return -EINVAL;
+ }
+ return read_private_key(sig_params->keyfile, pkey_ret);
+}
+
LIBEXPORT int
libfsverity_sign_digest(const struct libfsverity_digest *digest,
const struct libfsverity_signature_params *sig_params,
u8 **sig_ret, size_t *sig_size_ret)
{
const struct fsverity_hash_alg *hash_alg;
- EVP_PKEY *pkey = NULL;
X509 *cert = NULL;
+ EVP_PKEY *pkey = NULL;
const EVP_MD *md;
struct fsverity_formatted_digest *d = NULL;
int err;
@@ -334,11 +415,6 @@ libfsverity_sign_digest(const struct libfsverity_digest *digest,
return -EINVAL;
}
- if (!sig_params->keyfile || !sig_params->certfile) {
- libfsverity_error_msg("keyfile and certfile must be specified");
- return -EINVAL;
- }
-
if (!libfsverity_mem_is_zeroed(sig_params->reserved1,
sizeof(sig_params->reserved1)) ||
!libfsverity_mem_is_zeroed(sig_params->reserved2,
@@ -353,11 +429,11 @@ libfsverity_sign_digest(const struct libfsverity_digest *digest,
return -EINVAL;
}
- err = read_private_key(sig_params->keyfile, &pkey);
+ err = read_certificate(sig_params->certfile, &cert);
if (err)
goto out;
- err = read_certificate(sig_params->certfile, &cert);
+ err = get_private_key(sig_params, &pkey);
if (err)
goto out;
@@ -383,8 +459,8 @@ libfsverity_sign_digest(const struct libfsverity_digest *digest,
err = sign_pkcs7(d, sizeof(*d) + digest->digest_size,
pkey, cert, md, sig_ret, sig_size_ret);
out:
- EVP_PKEY_free(pkey);
X509_free(cert);
+ EVP_PKEY_free(pkey);
free(d);
return err;
}