diff options
Diffstat (limited to 'ubifs-utils/mkfs.ubifs/sign.c')
-rw-r--r-- | ubifs-utils/mkfs.ubifs/sign.c | 410 |
1 files changed, 0 insertions, 410 deletions
diff --git a/ubifs-utils/mkfs.ubifs/sign.c b/ubifs-utils/mkfs.ubifs/sign.c deleted file mode 100644 index 7f284f8..0000000 --- a/ubifs-utils/mkfs.ubifs/sign.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (C) 2018 Pengutronix - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: Sascha Hauer - */ - -#include "mkfs.ubifs.h" -#include "common.h" - -#include <openssl/evp.h> -#include <openssl/opensslv.h> -#include <openssl/bio.h> -#include <openssl/pem.h> -#include <openssl/err.h> -#include <openssl/engine.h> -#include <openssl/cms.h> -#include <openssl/conf.h> -#include <err.h> - -static struct ubifs_info *c = &info_; - -EVP_MD_CTX *hash_md; -const EVP_MD *md; - -int authenticated(void) -{ - return c->hash_algo_name != NULL; -} - -static int match_string(const char * const *array, size_t n, const char *string) -{ - int index; - const char *item; - - for (index = 0; index < n; index++) { - item = array[index]; - if (!item) - break; - if (!strcmp(item, string)) - return index; - } - - return -EINVAL; -} - -#include <linux/hash_info.h> - -const char *const hash_algo_name[HASH_ALGO__LAST] = { - [HASH_ALGO_MD4] = "md4", - [HASH_ALGO_MD5] = "md5", - [HASH_ALGO_SHA1] = "sha1", - [HASH_ALGO_RIPE_MD_160] = "rmd160", - [HASH_ALGO_SHA256] = "sha256", - [HASH_ALGO_SHA384] = "sha384", - [HASH_ALGO_SHA512] = "sha512", - [HASH_ALGO_SHA224] = "sha224", - [HASH_ALGO_RIPE_MD_128] = "rmd128", - [HASH_ALGO_RIPE_MD_256] = "rmd256", - [HASH_ALGO_RIPE_MD_320] = "rmd320", - [HASH_ALGO_WP_256] = "wp256", - [HASH_ALGO_WP_384] = "wp384", - [HASH_ALGO_WP_512] = "wp512", - [HASH_ALGO_TGR_128] = "tgr128", - [HASH_ALGO_TGR_160] = "tgr160", - [HASH_ALGO_TGR_192] = "tgr192", - [HASH_ALGO_SM3_256] = "sm3-256", -}; - -static void display_openssl_errors(int l) -{ - const char *file; - char buf[120]; - int e, line; - - if (ERR_peek_error() == 0) - return; - fprintf(stderr, "At main.c:%d:\n", l); - - while ((e = ERR_get_error_line(&file, &line))) { - ERR_error_string(e, buf); - fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line); - } -} - -static void drain_openssl_errors(void) -{ - const char *file; - int line; - - if (ERR_peek_error() == 0) - return; - while (ERR_get_error_line(&file, &line)) {} -} - -#define ssl_err_msg(fmt, ...) ({ \ - display_openssl_errors(__LINE__); \ - err_msg(fmt, ## __VA_ARGS__); \ - -1; \ -}) - -static const char *key_pass; - -static int pem_pw_cb(char *buf, int len, __attribute__((unused)) int w, - __attribute__((unused)) void *v) -{ - int pwlen; - - if (!key_pass) - return -1; - - pwlen = strlen(key_pass); - if (pwlen >= len) - return -1; - - strcpy(buf, key_pass); - - /* If it's wrong, don't keep trying it. */ - key_pass = NULL; - - return pwlen; -} - -static EVP_PKEY *read_private_key(const char *private_key_name, X509 **cert) -{ - EVP_PKEY *private_key = NULL; - int err; - - *cert = NULL; - - if (!strncmp(private_key_name, "pkcs11:", 7)) { - ENGINE *e; - struct { - const char *url; - X509 *cert; - } parms = { - .url = private_key_name, - }; - - ENGINE_load_builtin_engines(); - drain_openssl_errors(); - e = ENGINE_by_id("pkcs11"); - if (!e) { - ssl_err_msg("Load PKCS#11 ENGINE"); - return NULL; - } - - if (ENGINE_init(e)) { - drain_openssl_errors(); - } else { - ssl_err_msg("ENGINE_init"); - return NULL; - } - - if (key_pass) - if (!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0)) { - ssl_err_msg("Set PKCS#11 PIN"); - return NULL; - } - - private_key = ENGINE_load_private_key(e, private_key_name, - NULL, NULL); - - err = ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 0); - if (!err || !parms.cert) { - ssl_err_msg("Load certificate"); - } - *cert = parms.cert; - fprintf(stderr, "Using cert %p\n", *cert); - } else { - BIO *b; - - b = BIO_new_file(private_key_name, "rb"); - if (!b) - goto out; - - private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, - NULL); - BIO_free(b); - } -out: - if (!private_key) - ssl_err_msg("failed opening private key %s", private_key_name); - - return private_key; -} - -static X509 *read_x509(const char *x509_name) -{ - unsigned char buf[2]; - X509 *x509 = NULL; - BIO *b; - int n; - - b = BIO_new_file(x509_name, "rb"); - if (!b) - goto out; - - /* Look at the first two bytes of the file to determine the encoding */ - n = BIO_read(b, buf, 2); - if (n != 2) { - if (BIO_should_retry(b)) - err_msg("%s: Read wanted retry", x509_name); - if (n >= 0) - err_msg("%s: Short read", x509_name); - goto out; - } - - if (BIO_reset(b)) - goto out; - - if (buf[0] == 0x30 && buf[1] >= 0x81 && buf[1] <= 0x84) - /* Assume raw DER encoded X.509 */ - x509 = d2i_X509_bio(b, NULL); - else - /* Assume PEM encoded X.509 */ - x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); - - BIO_free(b); - -out: - if (!x509) { - ssl_err_msg("%s", x509_name); - return NULL; - } - - return x509; -} - -int sign_superblock_node(void *node) -{ - EVP_PKEY *private_key; - CMS_ContentInfo *cms = NULL; - X509 *cert = NULL; - BIO *bd, *bm; - void *obuf; - long len; - int ret; - void *pret; - struct ubifs_sig_node *sig = node + UBIFS_SB_NODE_SZ; - - if (!authenticated()) - return 0; - - ERR_load_crypto_strings(); - ERR_clear_error(); - - key_pass = getenv("MKFS_UBIFS_SIGN_PIN"); - - bm = BIO_new_mem_buf(node, UBIFS_SB_NODE_SZ); - - private_key = read_private_key(c->auth_key_filename, &cert); - if (!private_key) - return -1; - - if (!cert) { - if (!c->auth_cert_filename) - return err_msg("authentication certificate not provided (--auth-cert)"); - cert = read_x509(c->auth_cert_filename); - } - - if (!cert) - return -1; - - OpenSSL_add_all_digests(); - display_openssl_errors(__LINE__); - - cms = CMS_sign(NULL, NULL, NULL, NULL, - CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | - CMS_DETACHED | CMS_STREAM); - if (!cms) - return err_msg("CMS_sign failed"); - - pret = CMS_add1_signer(cms, cert, private_key, md, - CMS_NOCERTS | CMS_BINARY | - CMS_NOSMIMECAP | CMS_NOATTR); - if (!pret) - return err_msg("CMS_add1_signer failed"); - - ret = CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY); - if (!ret) - return err_msg("CMS_final failed"); - - bd = BIO_new(BIO_s_mem()); - - ret = i2d_CMS_bio_stream(bd, cms, NULL, 0); - if (!ret) - return err_msg("i2d_CMS_bio_stream failed"); - - len = BIO_get_mem_data(bd, &obuf); - - sig->type = UBIFS_SIGNATURE_TYPE_PKCS7; - sig->len = cpu_to_le32(len); - sig->ch.node_type = UBIFS_SIG_NODE; - - memcpy(sig + 1, obuf, len); - - BIO_free(bd); - BIO_free(bm); - - return 0; -} - -/** - * ubifs_node_calc_hash - calculate the hash of a UBIFS node - * @c: UBIFS file-system description object - * @node: the node to calculate a hash for - * @hash: the returned hash - */ -void ubifs_node_calc_hash(const void *node, uint8_t *hash) -{ - const struct ubifs_ch *ch = node; - unsigned int md_len; - - if (!authenticated()) - return; - - EVP_DigestInit_ex(hash_md, md, NULL); - EVP_DigestUpdate(hash_md, node, le32_to_cpu(ch->len)); - EVP_DigestFinal_ex(hash_md, hash, &md_len); -} - -/** - * mst_node_calc_hash - calculate the hash of a UBIFS master node - * @c: UBIFS file-system description object - * @node: the node to calculate a hash for - * @hash: the returned hash - */ -void mst_node_calc_hash(const void *node, uint8_t *hash) -{ - unsigned int md_len; - - if (!authenticated()) - return; - - EVP_DigestInit_ex(hash_md, md, NULL); - EVP_DigestUpdate(hash_md, node + sizeof(struct ubifs_ch), - UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch)); - EVP_DigestFinal_ex(hash_md, hash, &md_len); -} - -void hash_digest_init(void) -{ - if (!authenticated()) - return; - - EVP_DigestInit_ex(hash_md, md, NULL); -} - -void hash_digest_update(const void *buf, int len) -{ - if (!authenticated()) - return; - - EVP_DigestUpdate(hash_md, buf, len); -} - -void hash_digest_final(void *hash, unsigned int *len) -{ - if (!authenticated()) - return; - - EVP_DigestFinal_ex(hash_md, hash, len); -} - -int init_authentication(void) -{ - int hash_algo; - - if (!c->auth_key_filename && !c->auth_cert_filename && !c->hash_algo_name) - return 0; - - if (!c->auth_key_filename) - return err_msg("authentication key not given (--auth-key)"); - - if (!c->hash_algo_name) - return err_msg("Hash algorithm not given (--hash-algo)"); - - OPENSSL_config(NULL); - - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - - md = EVP_get_digestbyname(c->hash_algo_name); - if (!md) - return err_msg("Unknown message digest %s", c->hash_algo_name); - - hash_md = EVP_MD_CTX_create(); - c->hash_len = EVP_MD_size(md); - - hash_algo = match_string(hash_algo_name, HASH_ALGO__LAST, c->hash_algo_name); - if (hash_algo < 0) - return err_msg("Unsupported message digest %s", c->hash_algo_name); - - c->hash_algo = hash_algo; - - return 0; -} |