Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | // SPDX-License-Identifier: GPL-2.0+ /* * Check a file including a preload header including a signature * * Copyright (c) 2025 Paul HENRYS <paul.henrys_ext@softathome.com> * * Binman makes it possible to generate a preload header signing part or the * complete file. The tool preload_check_sign allows to verify and authenticate * a file starting with a preload header. */ #include <stdio.h> #include <unistd.h> #include <openssl/pem.h> #include <openssl/evp.h> #include <openssl/err.h> #include <image.h> extern void image_pre_load_sig_set_info(struct image_sig_info *info); extern int image_pre_load_sig(ulong addr); static void usage(char *cmdname) { fprintf(stderr, "Usage: %s -f file -k PEM key file\n" " -f ==> set file which should be checked\n" " -k ==> PEM key file\n" " -a ==> algo (default: sha256,rsa2048)\n" " -p ==> padding (default: pkcs-1.5)\n" " -h ==> help\n", cmdname); exit(EXIT_FAILURE); } int main(int argc, char **argv) { int ret = 0; char cmdname[256]; char *file = NULL; char *keyfile = NULL; int c; FILE *fp = NULL; FILE *fp_key = NULL; size_t bytes; long filesize; void *buffer = NULL; EVP_PKEY *pkey = NULL; char *algo = "sha256,rsa2048"; char *padding = "pkcs-1.5"; struct image_sig_info info = {0}; strncpy(cmdname, *argv, sizeof(cmdname) - 1); cmdname[sizeof(cmdname) - 1] = '\0'; while ((c = getopt(argc, argv, "f:k:a:p:h")) != -1) switch (c) { case 'f': file = optarg; break; case 'k': keyfile = optarg; break; case 'a': algo = optarg; break; case 'p': padding = optarg; break; default: usage(cmdname); break; } if (!file) { fprintf(stderr, "%s: Missing file\n", *argv); usage(*argv); } if (!keyfile) { fprintf(stderr, "%s: Missing key file\n", *argv); usage(*argv); } fp = fopen(file, "r"); if (!fp) { fprintf(stderr, "Error opening file: %s\n", file); ret = EXIT_FAILURE; goto out; } fseek(fp, 0, SEEK_END); filesize = ftell(fp); rewind(fp); buffer = malloc(filesize); if (!buffer) { fprintf(stderr, "Memory allocation failed"); ret = EXIT_FAILURE; goto out; } bytes = fread(buffer, 1, filesize, fp); if (bytes != filesize) { fprintf(stderr, "Error reading file\n"); ret = EXIT_FAILURE; goto out; } fp_key = fopen(keyfile, "r"); if (!fp_key) { fprintf(stderr, "Error opening file: %s\n", keyfile); ret = EXIT_FAILURE; goto out; } /* Attempt to read the private key */ pkey = PEM_read_PrivateKey(fp_key, NULL, NULL, NULL); if (!pkey) { /* If private key reading fails, try reading as a public key */ fseek(fp_key, 0, SEEK_SET); pkey = PEM_read_PUBKEY(fp_key, NULL, NULL, NULL); } if (!pkey) { fprintf(stderr, "Unable to retrieve the public key: %s\n", ERR_error_string(ERR_get_error(), NULL)); ret = EXIT_FAILURE; goto out; } info.algo_name = algo; info.padding_name = padding; info.key = (uint8_t *)pkey; info.mandatory = 1; info.sig_size = EVP_PKEY_size(pkey); if (info.sig_size < 0) { fprintf(stderr, "Fail to retrieve the signature size: %s\n", ERR_error_string(ERR_get_error(), NULL)); ret = EXIT_FAILURE; goto out; } /* Compute signature information */ info.sig_info.name = info.algo_name; info.sig_info.padding = image_get_padding_algo(info.padding_name); info.sig_info.checksum = image_get_checksum_algo(info.sig_info.name); info.sig_info.crypto = image_get_crypto_algo(info.sig_info.name); info.sig_info.key = info.key; info.sig_info.keylen = info.key_len; /* Check the signature */ image_pre_load_sig_set_info(&info); ret = image_pre_load_sig((ulong)buffer); out: if (fp) fclose(fp); if (fp_key) fclose(fp_key); if (info.key) EVP_PKEY_free(pkey); free(buffer); exit(ret); } |