Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scripts/sign-file.c: Add support for signing with a raw signature

This patch adds support for signing a kernel module with a raw
detached PKCS#7 signature/message.

The signature is not converted and is simply appended to the module so
it needs to be in the right format. Using openssl, a valid signature can
be generated like this:
$ openssl smime -sign -nocerts -noattr -binary -in <module> -inkey \
<key> -signer <x509> -outform der -out <raw sig>

The resulting raw signature from the above command is (more or less)
identical to the raw signature that sign-file itself can produce like
this:
$ scripts/sign-file -d <hash algo> <key> <x509> <module>

Signed-off-by: Juerg Haefliger <juerg.haefliger@hpe.com>
Signed-off-by: David Howells <dhowells@redhat.com>

authored by

Juerg Haefliger and committed by
David Howells
e5a2e3c8 a1f2bdf3

+153 -97
+153 -97
scripts/sign-file.c
··· 2 2 * 3 3 * Copyright © 2014-2015 Red Hat, Inc. All Rights Reserved. 4 4 * Copyright © 2015 Intel Corporation. 5 + * Copyright © 2016 Hewlett Packard Enterprise Development LP 5 6 * 6 7 * Authors: David Howells <dhowells@redhat.com> 7 8 * David Woodhouse <dwmw2@infradead.org> 9 + * Juerg Haefliger <juerg.haefliger@hpe.com> 8 10 * 9 11 * This program is free software; you can redistribute it and/or 10 12 * modify it under the terms of the GNU Lesser General Public License ··· 69 67 { 70 68 fprintf(stderr, 71 69 "Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n"); 70 + fprintf(stderr, 71 + " scripts/sign-file -s <raw sig> <hash algo> <x509> <module> [<dest>]\n"); 72 72 exit(2); 73 73 } 74 74 ··· 130 126 return pwlen; 131 127 } 132 128 129 + static EVP_PKEY *read_private_key(const char *private_key_name) 130 + { 131 + EVP_PKEY *private_key; 132 + 133 + if (!strncmp(private_key_name, "pkcs11:", 7)) { 134 + ENGINE *e; 135 + 136 + ENGINE_load_builtin_engines(); 137 + drain_openssl_errors(); 138 + e = ENGINE_by_id("pkcs11"); 139 + ERR(!e, "Load PKCS#11 ENGINE"); 140 + if (ENGINE_init(e)) 141 + drain_openssl_errors(); 142 + else 143 + ERR(1, "ENGINE_init"); 144 + if (key_pass) 145 + ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), 146 + "Set PKCS#11 PIN"); 147 + private_key = ENGINE_load_private_key(e, private_key_name, 148 + NULL, NULL); 149 + ERR(!private_key, "%s", private_key_name); 150 + } else { 151 + BIO *b; 152 + 153 + b = BIO_new_file(private_key_name, "rb"); 154 + ERR(!b, "%s", private_key_name); 155 + private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, 156 + NULL); 157 + ERR(!private_key, "%s", private_key_name); 158 + BIO_free(b); 159 + } 160 + 161 + return private_key; 162 + } 163 + 164 + static X509 *read_x509(const char *x509_name) 165 + { 166 + X509 *x509; 167 + BIO *b; 168 + 169 + b = BIO_new_file(x509_name, "rb"); 170 + ERR(!b, "%s", x509_name); 171 + x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */ 172 + if (!x509) { 173 + ERR(BIO_reset(b) != 1, "%s", x509_name); 174 + x509 = PEM_read_bio_X509(b, NULL, NULL, 175 + NULL); /* PEM encoded X.509 */ 176 + if (x509) 177 + drain_openssl_errors(); 178 + } 179 + BIO_free(b); 180 + ERR(!x509, "%s", x509_name); 181 + 182 + return x509; 183 + } 184 + 133 185 int main(int argc, char **argv) 134 186 { 135 187 struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 }; 136 188 char *hash_algo = NULL; 137 - char *private_key_name, *x509_name, *module_name, *dest_name; 189 + char *private_key_name = NULL, *raw_sig_name = NULL; 190 + char *x509_name, *module_name, *dest_name; 138 191 bool save_sig = false, replace_orig; 139 192 bool sign_only = false; 193 + bool raw_sig = false; 140 194 unsigned char buf[4096]; 141 195 unsigned long module_size, sig_size; 142 196 unsigned int use_signed_attrs; 143 197 const EVP_MD *digest_algo; 144 198 EVP_PKEY *private_key; 145 199 #ifndef USE_PKCS7 146 - CMS_ContentInfo *cms; 200 + CMS_ContentInfo *cms = NULL; 147 201 unsigned int use_keyid = 0; 148 202 #else 149 - PKCS7 *pkcs7; 203 + PKCS7 *pkcs7 = NULL; 150 204 #endif 151 205 X509 *x509; 152 - BIO *b, *bd = NULL, *bm; 206 + BIO *bd, *bm; 153 207 int opt, n; 154 208 OpenSSL_add_all_algorithms(); 155 209 ERR_load_crypto_strings(); ··· 222 160 #endif 223 161 224 162 do { 225 - opt = getopt(argc, argv, "dpk"); 163 + opt = getopt(argc, argv, "sdpk"); 226 164 switch (opt) { 165 + case 's': raw_sig = true; break; 227 166 case 'p': save_sig = true; break; 228 167 case 'd': sign_only = true; save_sig = true; break; 229 168 #ifndef USE_PKCS7 ··· 240 177 if (argc < 4 || argc > 5) 241 178 format(); 242 179 243 - hash_algo = argv[0]; 244 - private_key_name = argv[1]; 180 + if (raw_sig) { 181 + raw_sig_name = argv[0]; 182 + hash_algo = argv[1]; 183 + } else { 184 + hash_algo = argv[0]; 185 + private_key_name = argv[1]; 186 + } 245 187 x509_name = argv[2]; 246 188 module_name = argv[3]; 247 189 if (argc == 5) { ··· 266 198 } 267 199 #endif 268 200 269 - /* Read the private key and the X.509 cert the PKCS#7 message 270 - * will point to. 271 - */ 272 - if (!strncmp(private_key_name, "pkcs11:", 7)) { 273 - ENGINE *e; 201 + /* Open the module file */ 202 + bm = BIO_new_file(module_name, "rb"); 203 + ERR(!bm, "%s", module_name); 274 204 275 - ENGINE_load_builtin_engines(); 276 - drain_openssl_errors(); 277 - e = ENGINE_by_id("pkcs11"); 278 - ERR(!e, "Load PKCS#11 ENGINE"); 279 - if (ENGINE_init(e)) 280 - drain_openssl_errors(); 281 - else 282 - ERR(1, "ENGINE_init"); 283 - if (key_pass) 284 - ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN"); 285 - private_key = ENGINE_load_private_key(e, private_key_name, NULL, 286 - NULL); 287 - ERR(!private_key, "%s", private_key_name); 288 - } else { 289 - b = BIO_new_file(private_key_name, "rb"); 290 - ERR(!b, "%s", private_key_name); 291 - private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, NULL); 292 - ERR(!private_key, "%s", private_key_name); 293 - BIO_free(b); 294 - } 205 + if (!raw_sig) { 206 + /* Read the private key and the X.509 cert the PKCS#7 message 207 + * will point to. 208 + */ 209 + private_key = read_private_key(private_key_name); 210 + x509 = read_x509(x509_name); 295 211 296 - b = BIO_new_file(x509_name, "rb"); 297 - ERR(!b, "%s", x509_name); 298 - x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */ 299 - if (!x509) { 300 - ERR(BIO_reset(b) != 1, "%s", x509_name); 301 - x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); /* PEM encoded X.509 */ 302 - if (x509) 303 - drain_openssl_errors(); 212 + /* Digest the module data. */ 213 + OpenSSL_add_all_digests(); 214 + display_openssl_errors(__LINE__); 215 + digest_algo = EVP_get_digestbyname(hash_algo); 216 + ERR(!digest_algo, "EVP_get_digestbyname"); 217 + 218 + #ifndef USE_PKCS7 219 + /* Load the signature message from the digest buffer. */ 220 + cms = CMS_sign(NULL, NULL, NULL, NULL, 221 + CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | 222 + CMS_DETACHED | CMS_STREAM); 223 + ERR(!cms, "CMS_sign"); 224 + 225 + ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, 226 + CMS_NOCERTS | CMS_BINARY | 227 + CMS_NOSMIMECAP | use_keyid | 228 + use_signed_attrs), 229 + "CMS_add1_signer"); 230 + ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0, 231 + "CMS_final"); 232 + 233 + #else 234 + pkcs7 = PKCS7_sign(x509, private_key, NULL, bm, 235 + PKCS7_NOCERTS | PKCS7_BINARY | 236 + PKCS7_DETACHED | use_signed_attrs); 237 + ERR(!pkcs7, "PKCS7_sign"); 238 + #endif 239 + 240 + if (save_sig) { 241 + char *sig_file_name; 242 + BIO *b; 243 + 244 + ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0, 245 + "asprintf"); 246 + b = BIO_new_file(sig_file_name, "wb"); 247 + ERR(!b, "%s", sig_file_name); 248 + #ifndef USE_PKCS7 249 + ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0, 250 + "%s", sig_file_name); 251 + #else 252 + ERR(i2d_PKCS7_bio(b, pkcs7) < 0, 253 + "%s", sig_file_name); 254 + #endif 255 + BIO_free(b); 256 + } 257 + 258 + if (sign_only) { 259 + BIO_free(bm); 260 + return 0; 261 + } 304 262 } 305 - BIO_free(b); 306 - ERR(!x509, "%s", x509_name); 307 263 308 264 /* Open the destination file now so that we can shovel the module data 309 265 * across as we read it. 310 266 */ 311 - if (!sign_only) { 312 - bd = BIO_new_file(dest_name, "wb"); 313 - ERR(!bd, "%s", dest_name); 314 - } 315 - 316 - /* Digest the module data. */ 317 - OpenSSL_add_all_digests(); 318 - display_openssl_errors(__LINE__); 319 - digest_algo = EVP_get_digestbyname(hash_algo); 320 - ERR(!digest_algo, "EVP_get_digestbyname"); 321 - 322 - bm = BIO_new_file(module_name, "rb"); 323 - ERR(!bm, "%s", module_name); 324 - 325 - #ifndef USE_PKCS7 326 - /* Load the signature message from the digest buffer. */ 327 - cms = CMS_sign(NULL, NULL, NULL, NULL, 328 - CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED | CMS_STREAM); 329 - ERR(!cms, "CMS_sign"); 330 - 331 - ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, 332 - CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP | 333 - use_keyid | use_signed_attrs), 334 - "CMS_add1_signer"); 335 - ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0, 336 - "CMS_final"); 337 - 338 - #else 339 - pkcs7 = PKCS7_sign(x509, private_key, NULL, bm, 340 - PKCS7_NOCERTS | PKCS7_BINARY | 341 - PKCS7_DETACHED | use_signed_attrs); 342 - ERR(!pkcs7, "PKCS7_sign"); 343 - #endif 344 - 345 - if (save_sig) { 346 - char *sig_file_name; 347 - 348 - ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0, 349 - "asprintf"); 350 - b = BIO_new_file(sig_file_name, "wb"); 351 - ERR(!b, "%s", sig_file_name); 352 - #ifndef USE_PKCS7 353 - ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0, 354 - "%s", sig_file_name); 355 - #else 356 - ERR(i2d_PKCS7_bio(b, pkcs7) < 0, 357 - "%s", sig_file_name); 358 - #endif 359 - BIO_free(b); 360 - } 361 - 362 - if (sign_only) 363 - return 0; 267 + bd = BIO_new_file(dest_name, "wb"); 268 + ERR(!bd, "%s", dest_name); 364 269 365 270 /* Append the marker and the PKCS#7 message to the destination file */ 366 271 ERR(BIO_reset(bm) < 0, "%s", module_name); ··· 341 300 n > 0) { 342 301 ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name); 343 302 } 303 + BIO_free(bm); 344 304 ERR(n < 0, "%s", module_name); 345 305 module_size = BIO_number_written(bd); 346 306 307 + if (!raw_sig) { 347 308 #ifndef USE_PKCS7 348 - ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name); 309 + ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name); 349 310 #else 350 - ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name); 311 + ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name); 351 312 #endif 313 + } else { 314 + BIO *b; 315 + 316 + /* Read the raw signature file and write the data to the 317 + * destination file 318 + */ 319 + b = BIO_new_file(raw_sig_name, "rb"); 320 + ERR(!b, "%s", raw_sig_name); 321 + while ((n = BIO_read(b, buf, sizeof(buf))), n > 0) 322 + ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name); 323 + BIO_free(b); 324 + } 325 + 352 326 sig_size = BIO_number_written(bd) - module_size; 353 327 sig_info.sig_len = htonl(sig_size); 354 328 ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name);