aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2015-08-13 22:08:39 -0400
committerJames Morris <james.l.morris@oracle.com>2015-08-13 22:08:39 -0400
commite4fc02f24c223ee8d668bf2d39bb8a2dbd61b40e (patch)
tree8ad26407ec8b8898f6ff5f396ff628919a56c624 /scripts
parentaa62efff65ba572814511efa68cb158fe9e960c4 (diff)
parente9a5e8cc55286941503f36c5b7485a5aa923b3f1 (diff)
Merge tag 'modsign-pkcs7-20150812-3' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile4
-rw-r--r--scripts/Makefile.modinst2
-rw-r--r--scripts/asn1_compiler.c229
-rw-r--r--scripts/extract-cert.c166
-rwxr-xr-xscripts/sign-file421
-rwxr-xr-xscripts/sign-file.c260
6 files changed, 573 insertions, 509 deletions
diff --git a/scripts/Makefile b/scripts/Makefile
index 2016a64497ab..1b2661712d44 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -16,9 +16,13 @@ hostprogs-$(CONFIG_VT) += conmakehash
16hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount 16hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
17hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable 17hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
18hostprogs-$(CONFIG_ASN1) += asn1_compiler 18hostprogs-$(CONFIG_ASN1) += asn1_compiler
19hostprogs-$(CONFIG_MODULE_SIG) += sign-file
20hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
19 21
20HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include 22HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
21HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include 23HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
24HOSTLOADLIBES_sign-file = -lcrypto
25HOSTLOADLIBES_extract-cert = -lcrypto
22 26
23always := $(hostprogs-y) $(hostprogs-m) 27always := $(hostprogs-y) $(hostprogs-m)
24 28
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index e48a4e9d8868..07650eeaaf06 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -22,7 +22,7 @@ quiet_cmd_modules_install = INSTALL $@
22 mkdir -p $(2) ; \ 22 mkdir -p $(2) ; \
23 cp $@ $(2) ; \ 23 cp $@ $(2) ; \
24 $(mod_strip_cmd) $(2)/$(notdir $@) ; \ 24 $(mod_strip_cmd) $(2)/$(notdir $@) ; \
25 $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) ; \ 25 $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) && \
26 $(mod_compress_cmd) $(2)/$(notdir $@) 26 $(mod_compress_cmd) $(2)/$(notdir $@)
27 27
28# Modules built outside the kernel source tree go into extra by default 28# Modules built outside the kernel source tree go into extra by default
diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c
index 1c75e22b6385..e000f44e37b8 100644
--- a/scripts/asn1_compiler.c
+++ b/scripts/asn1_compiler.c
@@ -13,6 +13,7 @@
13#include <stdio.h> 13#include <stdio.h>
14#include <stdlib.h> 14#include <stdlib.h>
15#include <stdint.h> 15#include <stdint.h>
16#include <stdbool.h>
16#include <string.h> 17#include <string.h>
17#include <ctype.h> 18#include <ctype.h>
18#include <unistd.h> 19#include <unistd.h>
@@ -293,8 +294,8 @@ static const char *const directives[NR__DIRECTIVES] = {
293 294
294struct action { 295struct action {
295 struct action *next; 296 struct action *next;
297 char *name;
296 unsigned char index; 298 unsigned char index;
297 char name[];
298}; 299};
299 300
300static struct action *action_list; 301static struct action *action_list;
@@ -305,15 +306,17 @@ struct token {
305 enum token_type token_type : 8; 306 enum token_type token_type : 8;
306 unsigned char size; 307 unsigned char size;
307 struct action *action; 308 struct action *action;
308 const char *value; 309 char *content;
309 struct type *type; 310 struct type *type;
310}; 311};
311 312
312static struct token *token_list; 313static struct token *token_list;
313static unsigned nr_tokens; 314static unsigned nr_tokens;
314static _Bool verbose; 315static bool verbose_opt;
316static bool debug_opt;
315 317
316#define debug(fmt, ...) do { if (verbose) printf(fmt, ## __VA_ARGS__); } while (0) 318#define verbose(fmt, ...) do { if (verbose_opt) printf(fmt, ## __VA_ARGS__); } while (0)
319#define debug(fmt, ...) do { if (debug_opt) printf(fmt, ## __VA_ARGS__); } while (0)
317 320
318static int directive_compare(const void *_key, const void *_pdir) 321static int directive_compare(const void *_key, const void *_pdir)
319{ 322{
@@ -325,11 +328,9 @@ static int directive_compare(const void *_key, const void *_pdir)
325 dlen = strlen(dir); 328 dlen = strlen(dir);
326 clen = (dlen < token->size) ? dlen : token->size; 329 clen = (dlen < token->size) ? dlen : token->size;
327 330
328 //debug("cmp(%*.*s,%s) = ", 331 //debug("cmp(%s,%s) = ", token->content, dir);
329 // (int)token->size, (int)token->size, token->value,
330 // dir);
331 332
332 val = memcmp(token->value, dir, clen); 333 val = memcmp(token->content, dir, clen);
333 if (val != 0) { 334 if (val != 0) {
334 //debug("%d [cmp]\n", val); 335 //debug("%d [cmp]\n", val);
335 return val; 336 return val;
@@ -349,7 +350,7 @@ static int directive_compare(const void *_key, const void *_pdir)
349static void tokenise(char *buffer, char *end) 350static void tokenise(char *buffer, char *end)
350{ 351{
351 struct token *tokens; 352 struct token *tokens;
352 char *line, *nl, *p, *q; 353 char *line, *nl, *start, *p, *q;
353 unsigned tix, lineno; 354 unsigned tix, lineno;
354 355
355 /* Assume we're going to have half as many tokens as we have 356 /* Assume we're going to have half as many tokens as we have
@@ -408,11 +409,11 @@ static void tokenise(char *buffer, char *end)
408 break; 409 break;
409 410
410 tokens[tix].line = lineno; 411 tokens[tix].line = lineno;
411 tokens[tix].value = p; 412 start = p;
412 413
413 /* Handle string tokens */ 414 /* Handle string tokens */
414 if (isalpha(*p)) { 415 if (isalpha(*p)) {
415 const char **dir; 416 const char **dir, *start = p;
416 417
417 /* Can be a directive, type name or element 418 /* Can be a directive, type name or element
418 * name. Find the end of the name. 419 * name. Find the end of the name.
@@ -423,10 +424,18 @@ static void tokenise(char *buffer, char *end)
423 tokens[tix].size = q - p; 424 tokens[tix].size = q - p;
424 p = q; 425 p = q;
425 426
427 tokens[tix].content = malloc(tokens[tix].size + 1);
428 if (!tokens[tix].content) {
429 perror(NULL);
430 exit(1);
431 }
432 memcpy(tokens[tix].content, start, tokens[tix].size);
433 tokens[tix].content[tokens[tix].size] = 0;
434
426 /* If it begins with a lowercase letter then 435 /* If it begins with a lowercase letter then
427 * it's an element name 436 * it's an element name
428 */ 437 */
429 if (islower(tokens[tix].value[0])) { 438 if (islower(tokens[tix].content[0])) {
430 tokens[tix++].token_type = TOKEN_ELEMENT_NAME; 439 tokens[tix++].token_type = TOKEN_ELEMENT_NAME;
431 continue; 440 continue;
432 } 441 }
@@ -455,6 +464,13 @@ static void tokenise(char *buffer, char *end)
455 q++; 464 q++;
456 tokens[tix].size = q - p; 465 tokens[tix].size = q - p;
457 p = q; 466 p = q;
467 tokens[tix].content = malloc(tokens[tix].size + 1);
468 if (!tokens[tix].content) {
469 perror(NULL);
470 exit(1);
471 }
472 memcpy(tokens[tix].content, start, tokens[tix].size);
473 tokens[tix].content[tokens[tix].size] = 0;
458 tokens[tix++].token_type = TOKEN_NUMBER; 474 tokens[tix++].token_type = TOKEN_NUMBER;
459 continue; 475 continue;
460 } 476 }
@@ -463,6 +479,7 @@ static void tokenise(char *buffer, char *end)
463 if (memcmp(p, "::=", 3) == 0) { 479 if (memcmp(p, "::=", 3) == 0) {
464 p += 3; 480 p += 3;
465 tokens[tix].size = 3; 481 tokens[tix].size = 3;
482 tokens[tix].content = "::=";
466 tokens[tix++].token_type = TOKEN_ASSIGNMENT; 483 tokens[tix++].token_type = TOKEN_ASSIGNMENT;
467 continue; 484 continue;
468 } 485 }
@@ -472,12 +489,14 @@ static void tokenise(char *buffer, char *end)
472 if (memcmp(p, "({", 2) == 0) { 489 if (memcmp(p, "({", 2) == 0) {
473 p += 2; 490 p += 2;
474 tokens[tix].size = 2; 491 tokens[tix].size = 2;
492 tokens[tix].content = "({";
475 tokens[tix++].token_type = TOKEN_OPEN_ACTION; 493 tokens[tix++].token_type = TOKEN_OPEN_ACTION;
476 continue; 494 continue;
477 } 495 }
478 if (memcmp(p, "})", 2) == 0) { 496 if (memcmp(p, "})", 2) == 0) {
479 p += 2; 497 p += 2;
480 tokens[tix].size = 2; 498 tokens[tix].size = 2;
499 tokens[tix].content = "})";
481 tokens[tix++].token_type = TOKEN_CLOSE_ACTION; 500 tokens[tix++].token_type = TOKEN_CLOSE_ACTION;
482 continue; 501 continue;
483 } 502 }
@@ -488,22 +507,27 @@ static void tokenise(char *buffer, char *end)
488 switch (*p) { 507 switch (*p) {
489 case '{': 508 case '{':
490 p += 1; 509 p += 1;
510 tokens[tix].content = "{";
491 tokens[tix++].token_type = TOKEN_OPEN_CURLY; 511 tokens[tix++].token_type = TOKEN_OPEN_CURLY;
492 continue; 512 continue;
493 case '}': 513 case '}':
494 p += 1; 514 p += 1;
515 tokens[tix].content = "}";
495 tokens[tix++].token_type = TOKEN_CLOSE_CURLY; 516 tokens[tix++].token_type = TOKEN_CLOSE_CURLY;
496 continue; 517 continue;
497 case '[': 518 case '[':
498 p += 1; 519 p += 1;
520 tokens[tix].content = "[";
499 tokens[tix++].token_type = TOKEN_OPEN_SQUARE; 521 tokens[tix++].token_type = TOKEN_OPEN_SQUARE;
500 continue; 522 continue;
501 case ']': 523 case ']':
502 p += 1; 524 p += 1;
525 tokens[tix].content = "]";
503 tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; 526 tokens[tix++].token_type = TOKEN_CLOSE_SQUARE;
504 continue; 527 continue;
505 case ',': 528 case ',':
506 p += 1; 529 p += 1;
530 tokens[tix].content = ",";
507 tokens[tix++].token_type = TOKEN_COMMA; 531 tokens[tix++].token_type = TOKEN_COMMA;
508 continue; 532 continue;
509 default: 533 default:
@@ -518,22 +542,20 @@ static void tokenise(char *buffer, char *end)
518 } 542 }
519 543
520 nr_tokens = tix; 544 nr_tokens = tix;
521 debug("Extracted %u tokens\n", nr_tokens); 545 verbose("Extracted %u tokens\n", nr_tokens);
522 546
523#if 0 547#if 0
524 { 548 {
525 int n; 549 int n;
526 for (n = 0; n < nr_tokens; n++) 550 for (n = 0; n < nr_tokens; n++)
527 debug("Token %3u: '%*.*s'\n", 551 debug("Token %3u: '%s'\n", n, token_list[n].content);
528 n,
529 (int)token_list[n].size, (int)token_list[n].size,
530 token_list[n].value);
531 } 552 }
532#endif 553#endif
533} 554}
534 555
535static void build_type_list(void); 556static void build_type_list(void);
536static void parse(void); 557static void parse(void);
558static void dump_elements(void);
537static void render(FILE *out, FILE *hdr); 559static void render(FILE *out, FILE *hdr);
538 560
539/* 561/*
@@ -548,16 +570,27 @@ int main(int argc, char **argv)
548 char *kbuild_verbose; 570 char *kbuild_verbose;
549 int fd; 571 int fd;
550 572
573 kbuild_verbose = getenv("KBUILD_VERBOSE");
574 if (kbuild_verbose)
575 verbose_opt = atoi(kbuild_verbose);
576
577 while (argc > 4) {
578 if (strcmp(argv[1], "-v") == 0)
579 verbose_opt = true;
580 else if (strcmp(argv[1], "-d") == 0)
581 debug_opt = true;
582 else
583 break;
584 memmove(&argv[1], &argv[2], (argc - 2) * sizeof(char *));
585 argc--;
586 }
587
551 if (argc != 4) { 588 if (argc != 4) {
552 fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n", 589 fprintf(stderr, "Format: %s [-v] [-d] <grammar-file> <c-file> <hdr-file>\n",
553 argv[0]); 590 argv[0]);
554 exit(2); 591 exit(2);
555 } 592 }
556 593
557 kbuild_verbose = getenv("KBUILD_VERBOSE");
558 if (kbuild_verbose)
559 verbose = atoi(kbuild_verbose);
560
561 filename = argv[1]; 594 filename = argv[1];
562 outputname = argv[2]; 595 outputname = argv[2];
563 headername = argv[3]; 596 headername = argv[3];
@@ -608,6 +641,7 @@ int main(int argc, char **argv)
608 tokenise(buffer, buffer + readlen); 641 tokenise(buffer, buffer + readlen);
609 build_type_list(); 642 build_type_list();
610 parse(); 643 parse();
644 dump_elements();
611 645
612 out = fopen(outputname, "w"); 646 out = fopen(outputname, "w");
613 if (!out) { 647 if (!out) {
@@ -693,7 +727,7 @@ static int type_index_compare(const void *_a, const void *_b)
693 if ((*a)->name->size != (*b)->name->size) 727 if ((*a)->name->size != (*b)->name->size)
694 return (*a)->name->size - (*b)->name->size; 728 return (*a)->name->size - (*b)->name->size;
695 else 729 else
696 return memcmp((*a)->name->value, (*b)->name->value, 730 return memcmp((*a)->name->content, (*b)->name->content,
697 (*a)->name->size); 731 (*a)->name->size);
698} 732}
699 733
@@ -706,7 +740,7 @@ static int type_finder(const void *_key, const void *_ti)
706 if (token->size != type->name->size) 740 if (token->size != type->name->size)
707 return token->size - type->name->size; 741 return token->size - type->name->size;
708 else 742 else
709 return memcmp(token->value, type->name->value, 743 return memcmp(token->content, type->name->content,
710 token->size); 744 token->size);
711} 745}
712 746
@@ -756,14 +790,11 @@ static void build_type_list(void)
756 790
757 qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); 791 qsort(type_index, nr, sizeof(type_index[0]), type_index_compare);
758 792
759 debug("Extracted %u types\n", nr_types); 793 verbose("Extracted %u types\n", nr_types);
760#if 0 794#if 0
761 for (n = 0; n < nr_types; n++) { 795 for (n = 0; n < nr_types; n++) {
762 struct type *type = type_index[n]; 796 struct type *type = type_index[n];
763 debug("- %*.*s\n", 797 debug("- %*.*s\n", type->name->content);
764 (int)type->name->size,
765 (int)type->name->size,
766 type->name->value);
767 } 798 }
768#endif 799#endif
769} 800}
@@ -793,15 +824,14 @@ static void parse(void)
793 type->element->type_def = type; 824 type->element->type_def = type;
794 825
795 if (cursor != type[1].name) { 826 if (cursor != type[1].name) {
796 fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", 827 fprintf(stderr, "%s:%d: Parse error at token '%s'\n",
797 filename, cursor->line, 828 filename, cursor->line, cursor->content);
798 (int)cursor->size, (int)cursor->size, cursor->value);
799 exit(1); 829 exit(1);
800 } 830 }
801 831
802 } while (type++, !(type->flags & TYPE_STOP_MARKER)); 832 } while (type++, !(type->flags & TYPE_STOP_MARKER));
803 833
804 debug("Extracted %u actions\n", nr_actions); 834 verbose("Extracted %u actions\n", nr_actions);
805} 835}
806 836
807static struct element *element_list; 837static struct element *element_list;
@@ -862,34 +892,31 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
862 cursor++; 892 cursor++;
863 break; 893 break;
864 default: 894 default:
865 fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", 895 fprintf(stderr, "%s:%d: Unrecognised tag class token '%s'\n",
866 filename, cursor->line, 896 filename, cursor->line, cursor->content);
867 (int)cursor->size, (int)cursor->size, cursor->value);
868 exit(1); 897 exit(1);
869 } 898 }
870 899
871 if (cursor >= end) 900 if (cursor >= end)
872 goto overrun_error; 901 goto overrun_error;
873 if (cursor->token_type != TOKEN_NUMBER) { 902 if (cursor->token_type != TOKEN_NUMBER) {
874 fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", 903 fprintf(stderr, "%s:%d: Missing tag number '%s'\n",
875 filename, cursor->line, 904 filename, cursor->line, cursor->content);
876 (int)cursor->size, (int)cursor->size, cursor->value);
877 exit(1); 905 exit(1);
878 } 906 }
879 907
880 element->tag &= ~0x1f; 908 element->tag &= ~0x1f;
881 element->tag |= strtoul(cursor->value, &p, 10); 909 element->tag |= strtoul(cursor->content, &p, 10);
882 element->flags |= ELEMENT_TAG_SPECIFIED; 910 element->flags |= ELEMENT_TAG_SPECIFIED;
883 if (p - cursor->value != cursor->size) 911 if (p - cursor->content != cursor->size)
884 abort(); 912 abort();
885 cursor++; 913 cursor++;
886 914
887 if (cursor >= end) 915 if (cursor >= end)
888 goto overrun_error; 916 goto overrun_error;
889 if (cursor->token_type != TOKEN_CLOSE_SQUARE) { 917 if (cursor->token_type != TOKEN_CLOSE_SQUARE) {
890 fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", 918 fprintf(stderr, "%s:%d: Missing closing square bracket '%s'\n",
891 filename, cursor->line, 919 filename, cursor->line, cursor->content);
892 (int)cursor->size, (int)cursor->size, cursor->value);
893 exit(1); 920 exit(1);
894 } 921 }
895 cursor++; 922 cursor++;
@@ -989,9 +1016,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
989 ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), 1016 ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]),
990 type_finder); 1017 type_finder);
991 if (!ref) { 1018 if (!ref) {
992 fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", 1019 fprintf(stderr, "%s:%d: Type '%s' undefined\n",
993 filename, cursor->line, 1020 filename, cursor->line, cursor->content);
994 (int)cursor->size, (int)cursor->size, cursor->value);
995 exit(1); 1021 exit(1);
996 } 1022 }
997 cursor->type = *ref; 1023 cursor->type = *ref;
@@ -1040,9 +1066,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
1040 break; 1066 break;
1041 1067
1042 default: 1068 default:
1043 fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", 1069 fprintf(stderr, "%s:%d: Token '%s' does not introduce a type\n",
1044 filename, cursor->line, 1070 filename, cursor->line, cursor->content);
1045 (int)cursor->size, (int)cursor->size, cursor->value);
1046 exit(1); 1071 exit(1);
1047 } 1072 }
1048 1073
@@ -1059,20 +1084,18 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
1059 if (cursor >= end) 1084 if (cursor >= end)
1060 goto overrun_error; 1085 goto overrun_error;
1061 if (cursor->token_type != TOKEN_ELEMENT_NAME) { 1086 if (cursor->token_type != TOKEN_ELEMENT_NAME) {
1062 fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", 1087 fprintf(stderr, "%s:%d: Token '%s' is not an action function name\n",
1063 filename, cursor->line, 1088 filename, cursor->line, cursor->content);
1064 (int)cursor->size, (int)cursor->size, cursor->value);
1065 exit(1); 1089 exit(1);
1066 } 1090 }
1067 1091
1068 action = malloc(sizeof(struct action) + cursor->size + 1); 1092 action = malloc(sizeof(struct action));
1069 if (!action) { 1093 if (!action) {
1070 perror(NULL); 1094 perror(NULL);
1071 exit(1); 1095 exit(1);
1072 } 1096 }
1073 action->index = 0; 1097 action->index = 0;
1074 memcpy(action->name, cursor->value, cursor->size); 1098 action->name = cursor->content;
1075 action->name[cursor->size] = 0;
1076 1099
1077 for (ppaction = &action_list; 1100 for (ppaction = &action_list;
1078 *ppaction; 1101 *ppaction;
@@ -1102,9 +1125,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
1102 if (cursor >= end) 1125 if (cursor >= end)
1103 goto overrun_error; 1126 goto overrun_error;
1104 if (cursor->token_type != TOKEN_CLOSE_ACTION) { 1127 if (cursor->token_type != TOKEN_CLOSE_ACTION) {
1105 fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", 1128 fprintf(stderr, "%s:%d: Missing close action, got '%s'\n",
1106 filename, cursor->line, 1129 filename, cursor->line, cursor->content);
1107 (int)cursor->size, (int)cursor->size, cursor->value);
1108 exit(1); 1130 exit(1);
1109 } 1131 }
1110 cursor++; 1132 cursor++;
@@ -1114,9 +1136,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
1114 return top; 1136 return top;
1115 1137
1116parse_error: 1138parse_error:
1117 fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", 1139 fprintf(stderr, "%s:%d: Unexpected token '%s'\n",
1118 filename, cursor->line, 1140 filename, cursor->line, cursor->content);
1119 (int)cursor->size, (int)cursor->size, cursor->value);
1120 exit(1); 1141 exit(1);
1121 1142
1122overrun_error: 1143overrun_error:
@@ -1134,9 +1155,8 @@ static struct element *parse_compound(struct token **_cursor, struct token *end,
1134 struct token *cursor = *_cursor, *name; 1155 struct token *cursor = *_cursor, *name;
1135 1156
1136 if (cursor->token_type != TOKEN_OPEN_CURLY) { 1157 if (cursor->token_type != TOKEN_OPEN_CURLY) {
1137 fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", 1158 fprintf(stderr, "%s:%d: Expected compound to start with brace not '%s'\n",
1138 filename, cursor->line, 1159 filename, cursor->line, cursor->content);
1139 (int)cursor->size, (int)cursor->size, cursor->value);
1140 exit(1); 1160 exit(1);
1141 } 1161 }
1142 cursor++; 1162 cursor++;
@@ -1177,9 +1197,8 @@ static struct element *parse_compound(struct token **_cursor, struct token *end,
1177 children->flags &= ~ELEMENT_CONDITIONAL; 1197 children->flags &= ~ELEMENT_CONDITIONAL;
1178 1198
1179 if (cursor->token_type != TOKEN_CLOSE_CURLY) { 1199 if (cursor->token_type != TOKEN_CLOSE_CURLY) {
1180 fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", 1200 fprintf(stderr, "%s:%d: Expected compound closure, got '%s'\n",
1181 filename, cursor->line, 1201 filename, cursor->line, cursor->content);
1182 (int)cursor->size, (int)cursor->size, cursor->value);
1183 exit(1); 1202 exit(1);
1184 } 1203 }
1185 cursor++; 1204 cursor++;
@@ -1192,6 +1211,52 @@ overrun_error:
1192 exit(1); 1211 exit(1);
1193} 1212}
1194 1213
1214static void dump_element(const struct element *e, int level)
1215{
1216 const struct element *c;
1217 const struct type *t = e->type_def;
1218 const char *name = e->name ? e->name->content : ".";
1219 const char *tname = t && t->name ? t->name->content : ".";
1220 char tag[32];
1221
1222 if (e->class == 0 && e->method == 0 && e->tag == 0)
1223 strcpy(tag, "<...>");
1224 else if (e->class == ASN1_UNIV)
1225 sprintf(tag, "%s %s %s",
1226 asn1_classes[e->class],
1227 asn1_methods[e->method],
1228 asn1_universal_tags[e->tag]);
1229 else
1230 sprintf(tag, "%s %s %u",
1231 asn1_classes[e->class],
1232 asn1_methods[e->method],
1233 e->tag);
1234
1235 printf("%c%c%c%c%c %c %*s[*] \e[33m%s\e[m %s %s \e[35m%s\e[m\n",
1236 e->flags & ELEMENT_IMPLICIT ? 'I' : '-',
1237 e->flags & ELEMENT_EXPLICIT ? 'E' : '-',
1238 e->flags & ELEMENT_TAG_SPECIFIED ? 'T' : '-',
1239 e->flags & ELEMENT_SKIPPABLE ? 'S' : '-',
1240 e->flags & ELEMENT_CONDITIONAL ? 'C' : '-',
1241 "-tTqQcaro"[e->compound],
1242 level, "",
1243 tag,
1244 tname,
1245 name,
1246 e->action ? e->action->name : "");
1247 if (e->compound == TYPE_REF)
1248 dump_element(e->type->type->element, level + 3);
1249 else
1250 for (c = e->children; c; c = c->next)
1251 dump_element(c, level + 3);
1252}
1253
1254static void dump_elements(void)
1255{
1256 if (debug_opt)
1257 dump_element(type_list[0].element, 0);
1258}
1259
1195static void render_element(FILE *out, struct element *e, struct element *tag); 1260static void render_element(FILE *out, struct element *e, struct element *tag);
1196static void render_out_of_line_list(FILE *out); 1261static void render_out_of_line_list(FILE *out);
1197 1262
@@ -1293,7 +1358,7 @@ static void render(FILE *out, FILE *hdr)
1293 } 1358 }
1294 1359
1295 /* We do two passes - the first one calculates all the offsets */ 1360 /* We do two passes - the first one calculates all the offsets */
1296 debug("Pass 1\n"); 1361 verbose("Pass 1\n");
1297 nr_entries = 0; 1362 nr_entries = 0;
1298 root = &type_list[0]; 1363 root = &type_list[0];
1299 render_element(NULL, root->element, NULL); 1364 render_element(NULL, root->element, NULL);
@@ -1304,7 +1369,7 @@ static void render(FILE *out, FILE *hdr)
1304 e->flags &= ~ELEMENT_RENDERED; 1369 e->flags &= ~ELEMENT_RENDERED;
1305 1370
1306 /* And then we actually render */ 1371 /* And then we actually render */
1307 debug("Pass 2\n"); 1372 verbose("Pass 2\n");
1308 fprintf(out, "\n"); 1373 fprintf(out, "\n");
1309 fprintf(out, "static const unsigned char %s_machine[] = {\n", 1374 fprintf(out, "static const unsigned char %s_machine[] = {\n",
1310 grammar_name); 1375 grammar_name);
@@ -1390,9 +1455,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
1390 outofline = 1; 1455 outofline = 1;
1391 1456
1392 if (e->type_def && out) { 1457 if (e->type_def && out) {
1393 render_more(out, "\t// %*.*s\n", 1458 render_more(out, "\t// %s\n", e->type_def->name->content);
1394 (int)e->type_def->name->size, (int)e->type_def->name->size,
1395 e->type_def->name->value);
1396 } 1459 }
1397 1460
1398 /* Render the operation */ 1461 /* Render the operation */
@@ -1404,9 +1467,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
1404 render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,", 1467 render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,",
1405 cond, act, skippable ? "_OR_SKIP" : ""); 1468 cond, act, skippable ? "_OR_SKIP" : "");
1406 if (e->name) 1469 if (e->name)
1407 render_more(out, "\t\t// %*.*s", 1470 render_more(out, "\t\t// %s", e->name->content);
1408 (int)e->name->size, (int)e->name->size,
1409 e->name->value);
1410 render_more(out, "\n"); 1471 render_more(out, "\n");
1411 goto dont_render_tag; 1472 goto dont_render_tag;
1412 1473
@@ -1439,9 +1500,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
1439 1500
1440 x = tag ?: e; 1501 x = tag ?: e;
1441 if (x->name) 1502 if (x->name)
1442 render_more(out, "\t\t// %*.*s", 1503 render_more(out, "\t\t// %s", x->name->content);
1443 (int)x->name->size, (int)x->name->size,
1444 x->name->value);
1445 render_more(out, "\n"); 1504 render_more(out, "\n");
1446 1505
1447 /* Render the tag */ 1506 /* Render the tag */
@@ -1479,10 +1538,8 @@ dont_render_tag:
1479 * skipability */ 1538 * skipability */
1480 render_opcode(out, "_jump_target(%u),", e->entry_index); 1539 render_opcode(out, "_jump_target(%u),", e->entry_index);
1481 if (e->type_def && e->type_def->name) 1540 if (e->type_def && e->type_def->name)
1482 render_more(out, "\t\t// --> %*.*s", 1541 render_more(out, "\t\t// --> %s",
1483 (int)e->type_def->name->size, 1542 e->type_def->name->content);
1484 (int)e->type_def->name->size,
1485 e->type_def->name->value);
1486 render_more(out, "\n"); 1543 render_more(out, "\n");
1487 if (!(e->flags & ELEMENT_RENDERED)) { 1544 if (!(e->flags & ELEMENT_RENDERED)) {
1488 e->flags |= ELEMENT_RENDERED; 1545 e->flags |= ELEMENT_RENDERED;
@@ -1507,10 +1564,8 @@ dont_render_tag:
1507 * skipability */ 1564 * skipability */
1508 render_opcode(out, "_jump_target(%u),", e->entry_index); 1565 render_opcode(out, "_jump_target(%u),", e->entry_index);
1509 if (e->type_def && e->type_def->name) 1566 if (e->type_def && e->type_def->name)
1510 render_more(out, "\t\t// --> %*.*s", 1567 render_more(out, "\t\t// --> %s",
1511 (int)e->type_def->name->size, 1568 e->type_def->name->content);
1512 (int)e->type_def->name->size,
1513 e->type_def->name->value);
1514 render_more(out, "\n"); 1569 render_more(out, "\n");
1515 if (!(e->flags & ELEMENT_RENDERED)) { 1570 if (!(e->flags & ELEMENT_RENDERED)) {
1516 e->flags |= ELEMENT_RENDERED; 1571 e->flags |= ELEMENT_RENDERED;
diff --git a/scripts/extract-cert.c b/scripts/extract-cert.c
new file mode 100644
index 000000000000..fd0db015c65c
--- /dev/null
+++ b/scripts/extract-cert.c
@@ -0,0 +1,166 @@
1/* Extract X.509 certificate in DER form from PKCS#11 or PEM.
2 *
3 * Copyright © 2014 Red Hat, Inc. All Rights Reserved.
4 * Copyright © 2015 Intel Corporation.
5 *
6 * Authors: David Howells <dhowells@redhat.com>
7 * David Woodhouse <dwmw2@infradead.org>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public Licence
11 * as published by the Free Software Foundation; either version
12 * 2 of the Licence, or (at your option) any later version.
13 */
14#define _GNU_SOURCE
15#include <stdio.h>
16#include <stdlib.h>
17#include <stdint.h>
18#include <stdbool.h>
19#include <string.h>
20#include <getopt.h>
21#include <err.h>
22#include <arpa/inet.h>
23#include <openssl/bio.h>
24#include <openssl/evp.h>
25#include <openssl/pem.h>
26#include <openssl/pkcs7.h>
27#include <openssl/err.h>
28#include <openssl/engine.h>
29
30#define PKEY_ID_PKCS7 2
31
32static __attribute__((noreturn))
33void format(void)
34{
35 fprintf(stderr,
36 "Usage: scripts/extract-cert <source> <dest>\n");
37 exit(2);
38}
39
40static void display_openssl_errors(int l)
41{
42 const char *file;
43 char buf[120];
44 int e, line;
45
46 if (ERR_peek_error() == 0)
47 return;
48 fprintf(stderr, "At main.c:%d:\n", l);
49
50 while ((e = ERR_get_error_line(&file, &line))) {
51 ERR_error_string(e, buf);
52 fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line);
53 }
54}
55
56static void drain_openssl_errors(void)
57{
58 const char *file;
59 int line;
60
61 if (ERR_peek_error() == 0)
62 return;
63 while (ERR_get_error_line(&file, &line)) {}
64}
65
66#define ERR(cond, fmt, ...) \
67 do { \
68 bool __cond = (cond); \
69 display_openssl_errors(__LINE__); \
70 if (__cond) { \
71 err(1, fmt, ## __VA_ARGS__); \
72 } \
73 } while(0)
74
75static const char *key_pass;
76static BIO *wb;
77static char *cert_dst;
78int kbuild_verbose;
79
80static void write_cert(X509 *x509)
81{
82 char buf[200];
83
84 if (!wb) {
85 wb = BIO_new_file(cert_dst, "wb");
86 ERR(!wb, "%s", cert_dst);
87 }
88 X509_NAME_oneline(X509_get_subject_name(x509), buf, sizeof(buf));
89 ERR(!i2d_X509_bio(wb, x509), cert_dst);
90 if (kbuild_verbose)
91 fprintf(stderr, "Extracted cert: %s\n", buf);
92}
93
94int main(int argc, char **argv)
95{
96 char *cert_src;
97
98 OpenSSL_add_all_algorithms();
99 ERR_load_crypto_strings();
100 ERR_clear_error();
101
102 kbuild_verbose = atoi(getenv("KBUILD_VERBOSE")?:"0");
103
104 key_pass = getenv("KBUILD_SIGN_PIN");
105
106 if (argc != 3)
107 format();
108
109 cert_src = argv[1];
110 cert_dst = argv[2];
111
112 if (!cert_src[0]) {
113 /* Invoked with no input; create empty file */
114 FILE *f = fopen(cert_dst, "wb");
115 ERR(!f, "%s", cert_dst);
116 fclose(f);
117 exit(0);
118 } else if (!strncmp(cert_src, "pkcs11:", 7)) {
119 ENGINE *e;
120 struct {
121 const char *cert_id;
122 X509 *cert;
123 } parms;
124
125 parms.cert_id = cert_src;
126 parms.cert = NULL;
127
128 ENGINE_load_builtin_engines();
129 drain_openssl_errors();
130 e = ENGINE_by_id("pkcs11");
131 ERR(!e, "Load PKCS#11 ENGINE");
132 if (ENGINE_init(e))
133 drain_openssl_errors();
134 else
135 ERR(1, "ENGINE_init");
136 if (key_pass)
137 ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN");
138 ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1);
139 ERR(!parms.cert, "Get X.509 from PKCS#11");
140 write_cert(parms.cert);
141 } else {
142 BIO *b;
143 X509 *x509;
144
145 b = BIO_new_file(cert_src, "rb");
146 ERR(!b, "%s", cert_src);
147
148 while (1) {
149 x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
150 if (wb && !x509) {
151 unsigned long err = ERR_peek_last_error();
152 if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
153 ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
154 ERR_clear_error();
155 break;
156 }
157 }
158 ERR(!x509, "%s", cert_src);
159 write_cert(x509);
160 }
161 }
162
163 BIO_free(wb);
164
165 return 0;
166}
diff --git a/scripts/sign-file b/scripts/sign-file
deleted file mode 100755
index 3906ee1e2f76..000000000000
--- a/scripts/sign-file
+++ /dev/null
@@ -1,421 +0,0 @@
1#!/usr/bin/perl -w
2#
3# Sign a module file using the given key.
4#
5
6my $USAGE =
7"Usage: scripts/sign-file [-v] <hash algo> <key> <x509> <module> [<dest>]\n" .
8" scripts/sign-file [-v] -s <raw sig> <hash algo> <x509> <module> [<dest>]\n";
9
10use strict;
11use FileHandle;
12use IPC::Open2;
13use Getopt::Std;
14
15my %opts;
16getopts('vs:', \%opts) or die $USAGE;
17my $verbose = $opts{'v'};
18my $signature_file = $opts{'s'};
19
20die $USAGE if ($#ARGV > 4);
21die $USAGE if (!$signature_file && $#ARGV < 3 || $signature_file && $#ARGV < 2);
22
23my $dgst = shift @ARGV;
24my $private_key;
25if (!$signature_file) {
26 $private_key = shift @ARGV;
27}
28my $x509 = shift @ARGV;
29my $module = shift @ARGV;
30my ($dest, $keep_orig);
31if (@ARGV) {
32 $dest = $ARGV[0];
33 $keep_orig = 1;
34} else {
35 $dest = $module . "~";
36}
37
38die "Can't read private key\n" if (!$signature_file && !-r $private_key);
39die "Can't read signature file\n" if ($signature_file && !-r $signature_file);
40die "Can't read X.509 certificate\n" unless (-r $x509);
41die "Can't read module\n" unless (-r $module);
42
43#
44# Function to read the contents of a file into a variable.
45#
46sub read_file($)
47{
48 my ($file) = @_;
49 my $contents;
50 my $len;
51
52 open(FD, "<$file") || die $file;
53 binmode FD;
54 my @st = stat(FD);
55 die $file if (!@st);
56 $len = read(FD, $contents, $st[7]) || die $file;
57 close(FD) || die $file;
58 die "$file: Wanted length ", $st[7], ", got ", $len, "\n"
59 if ($len != $st[7]);
60 return $contents;
61}
62
63###############################################################################
64#
65# First of all, we have to parse the X.509 certificate to find certain details
66# about it.
67#
68# We read the DER-encoded X509 certificate and parse it to extract the Subject
69# name and Subject Key Identifier. Theis provides the data we need to build
70# the certificate identifier.
71#
72# The signer's name part of the identifier is fabricated from the commonName,
73# the organizationName or the emailAddress components of the X.509 subject
74# name.
75#
76# The subject key ID is used to select which of that signer's certificates
77# we're intending to use to sign the module.
78#
79###############################################################################
80my $x509_certificate = read_file($x509);
81
82my $UNIV = 0 << 6;
83my $APPL = 1 << 6;
84my $CONT = 2 << 6;
85my $PRIV = 3 << 6;
86
87my $CONS = 0x20;
88
89my $BOOLEAN = 0x01;
90my $INTEGER = 0x02;
91my $BIT_STRING = 0x03;
92my $OCTET_STRING = 0x04;
93my $NULL = 0x05;
94my $OBJ_ID = 0x06;
95my $UTF8String = 0x0c;
96my $SEQUENCE = 0x10;
97my $SET = 0x11;
98my $UTCTime = 0x17;
99my $GeneralizedTime = 0x18;
100
101my %OIDs = (
102 pack("CCC", 85, 4, 3) => "commonName",
103 pack("CCC", 85, 4, 6) => "countryName",
104 pack("CCC", 85, 4, 10) => "organizationName",
105 pack("CCC", 85, 4, 11) => "organizationUnitName",
106 pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption",
107 pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption",
108 pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress",
109 pack("CCC", 85, 29, 35) => "authorityKeyIdentifier",
110 pack("CCC", 85, 29, 14) => "subjectKeyIdentifier",
111 pack("CCC", 85, 29, 19) => "basicConstraints"
112);
113
114###############################################################################
115#
116# Extract an ASN.1 element from a string and return information about it.
117#
118###############################################################################
119sub asn1_extract($$@)
120{
121 my ($cursor, $expected_tag, $optional) = @_;
122
123 return [ -1 ]
124 if ($cursor->[1] == 0 && $optional);
125
126 die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n"
127 if ($cursor->[1] < 2);
128
129 my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2));
130
131 if ($expected_tag != -1 && $tag != $expected_tag) {
132 return [ -1 ]
133 if ($optional);
134 die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag,
135 " not ", $expected_tag, ")\n";
136 }
137
138 $cursor->[0] += 2;
139 $cursor->[1] -= 2;
140
141 die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n"
142 if (($tag & 0x1f) == 0x1f);
143 die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n"
144 if ($len == 0x80);
145
146 if ($len > 0x80) {
147 my $l = $len - 0x80;
148 die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n"
149 if ($cursor->[1] < $l);
150
151 if ($l == 0x1) {
152 $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
153 } elsif ($l == 0x2) {
154 $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
155 } elsif ($l == 0x3) {
156 $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
157 $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
158 } elsif ($l == 0x4) {
159 $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
160 } else {
161 die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
162 }
163
164 $cursor->[0] += $l;
165 $cursor->[1] -= $l;
166 }
167
168 die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n"
169 if ($cursor->[1] < $len);
170
171 my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ];
172 $cursor->[0] += $len;
173 $cursor->[1] -= $len;
174
175 return $ret;
176}
177
178###############################################################################
179#
180# Retrieve the data referred to by a cursor
181#
182###############################################################################
183sub asn1_retrieve($)
184{
185 my ($cursor) = @_;
186 my ($offset, $len, $data) = @$cursor;
187 return substr($$data, $offset, $len);
188}
189
190###############################################################################
191#
192# Roughly parse the X.509 certificate
193#
194###############################################################################
195my $cursor = [ 0, length($x509_certificate), \$x509_certificate ];
196
197my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE);
198my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE);
199my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1);
200my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER);
201my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
202my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
203my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
204my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
205my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
206my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1);
207my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1);
208my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1);
209
210my $subject_key_id = ();
211my $authority_key_id = ();
212
213#
214# Parse the extension list
215#
216if ($extension_list->[0] != -1) {
217 my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE);
218
219 while ($extensions->[1]->[1] > 0) {
220 my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE);
221 my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID);
222 my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1);
223 my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING);
224
225 my $raw_oid = asn1_retrieve($x_oid->[1]);
226 next if (!exists($OIDs{$raw_oid}));
227 my $x_type = $OIDs{$raw_oid};
228
229 my $raw_value = asn1_retrieve($x_val->[1]);
230
231 if ($x_type eq "subjectKeyIdentifier") {
232 my $vcursor = [ 0, length($raw_value), \$raw_value ];
233
234 $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING);
235 }
236 }
237}
238
239###############################################################################
240#
241# Determine what we're going to use as the signer's name. In order of
242# preference, take one of: commonName, organizationName or emailAddress.
243#
244###############################################################################
245my $org = "";
246my $cn = "";
247my $email = "";
248
249while ($subject->[1]->[1] > 0) {
250 my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET);
251 my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE);
252 my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID);
253 my $n_val = asn1_extract($attr->[1], -1);
254
255 my $raw_oid = asn1_retrieve($n_oid->[1]);
256 next if (!exists($OIDs{$raw_oid}));
257 my $n_type = $OIDs{$raw_oid};
258
259 my $raw_value = asn1_retrieve($n_val->[1]);
260
261 if ($n_type eq "organizationName") {
262 $org = $raw_value;
263 } elsif ($n_type eq "commonName") {
264 $cn = $raw_value;
265 } elsif ($n_type eq "emailAddress") {
266 $email = $raw_value;
267 }
268}
269
270my $signers_name = $email;
271
272if ($org && $cn) {
273 # Don't use the organizationName if the commonName repeats it
274 if (length($org) <= length($cn) &&
275 substr($cn, 0, length($org)) eq $org) {
276 $signers_name = $cn;
277 goto got_id_name;
278 }
279
280 # Or a signifcant chunk of it
281 if (length($org) >= 7 &&
282 length($cn) >= 7 &&
283 substr($cn, 0, 7) eq substr($org, 0, 7)) {
284 $signers_name = $cn;
285 goto got_id_name;
286 }
287
288 $signers_name = $org . ": " . $cn;
289} elsif ($org) {
290 $signers_name = $org;
291} elsif ($cn) {
292 $signers_name = $cn;
293}
294
295got_id_name:
296
297die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n"
298 if (!$subject_key_id);
299
300my $key_identifier = asn1_retrieve($subject_key_id->[1]);
301
302###############################################################################
303#
304# Create and attach the module signature
305#
306###############################################################################
307
308#
309# Signature parameters
310#
311my $algo = 1; # Public-key crypto algorithm: RSA
312my $hash = 0; # Digest algorithm
313my $id_type = 1; # Identifier type: X.509
314
315#
316# Digest the data
317#
318my $prologue;
319if ($dgst eq "sha1") {
320 $prologue = pack("C*",
321 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
322 0x2B, 0x0E, 0x03, 0x02, 0x1A,
323 0x05, 0x00, 0x04, 0x14);
324 $hash = 2;
325} elsif ($dgst eq "sha224") {
326 $prologue = pack("C*",
327 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
328 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
329 0x05, 0x00, 0x04, 0x1C);
330 $hash = 7;
331} elsif ($dgst eq "sha256") {
332 $prologue = pack("C*",
333 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
334 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
335 0x05, 0x00, 0x04, 0x20);
336 $hash = 4;
337} elsif ($dgst eq "sha384") {
338 $prologue = pack("C*",
339 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
340 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
341 0x05, 0x00, 0x04, 0x30);
342 $hash = 5;
343} elsif ($dgst eq "sha512") {
344 $prologue = pack("C*",
345 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
346 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
347 0x05, 0x00, 0x04, 0x40);
348 $hash = 6;
349} else {
350 die "Unknown hash algorithm: $dgst\n";
351}
352
353my $signature;
354if ($signature_file) {
355 $signature = read_file($signature_file);
356} else {
357 #
358 # Generate the digest and read from openssl's stdout
359 #
360 my $digest;
361 $digest = readpipe("openssl dgst -$dgst -binary $module") || die "openssl dgst";
362
363 #
364 # Generate the binary signature, which will be just the integer that
365 # comprises the signature with no metadata attached.
366 #
367 my $pid;
368 $pid = open2(*read_from, *write_to,
369 "openssl rsautl -sign -inkey $private_key -keyform PEM") ||
370 die "openssl rsautl";
371 binmode write_to;
372 print write_to $prologue . $digest || die "pipe to openssl rsautl";
373 close(write_to) || die "pipe to openssl rsautl";
374
375 binmode read_from;
376 read(read_from, $signature, 4096) || die "pipe from openssl rsautl";
377 close(read_from) || die "pipe from openssl rsautl";
378 waitpid($pid, 0) || die;
379 die "openssl rsautl died: $?" if ($? >> 8);
380}
381$signature = pack("n", length($signature)) . $signature,
382
383#
384# Build the signed binary
385#
386my $unsigned_module = read_file($module);
387
388my $magic_number = "~Module signature appended~\n";
389
390my $info = pack("CCCCCxxxN",
391 $algo, $hash, $id_type,
392 length($signers_name),
393 length($key_identifier),
394 length($signature));
395
396if ($verbose) {
397 print "Size of unsigned module: ", length($unsigned_module), "\n";
398 print "Size of signer's name : ", length($signers_name), "\n";
399 print "Size of key identifier : ", length($key_identifier), "\n";
400 print "Size of signature : ", length($signature), "\n";
401 print "Size of information : ", length($info), "\n";
402 print "Size of magic number : ", length($magic_number), "\n";
403 print "Signer's name : '", $signers_name, "'\n";
404 print "Digest : $dgst\n";
405}
406
407open(FD, ">$dest") || die $dest;
408binmode FD;
409print FD
410 $unsigned_module,
411 $signers_name,
412 $key_identifier,
413 $signature,
414 $info,
415 $magic_number
416 ;
417close FD || die $dest;
418
419if (!$keep_orig) {
420 rename($dest, $module) || die $module;
421}
diff --git a/scripts/sign-file.c b/scripts/sign-file.c
new file mode 100755
index 000000000000..058bba3103e2
--- /dev/null
+++ b/scripts/sign-file.c
@@ -0,0 +1,260 @@
1/* Sign a module file using the given key.
2 *
3 * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#define _GNU_SOURCE
12#include <stdio.h>
13#include <stdlib.h>
14#include <stdint.h>
15#include <stdbool.h>
16#include <string.h>
17#include <getopt.h>
18#include <err.h>
19#include <arpa/inet.h>
20#include <openssl/bio.h>
21#include <openssl/evp.h>
22#include <openssl/pem.h>
23#include <openssl/cms.h>
24#include <openssl/err.h>
25#include <openssl/engine.h>
26
27struct module_signature {
28 uint8_t algo; /* Public-key crypto algorithm [0] */
29 uint8_t hash; /* Digest algorithm [0] */
30 uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */
31 uint8_t signer_len; /* Length of signer's name [0] */
32 uint8_t key_id_len; /* Length of key identifier [0] */
33 uint8_t __pad[3];
34 uint32_t sig_len; /* Length of signature data */
35};
36
37#define PKEY_ID_PKCS7 2
38
39static char magic_number[] = "~Module signature appended~\n";
40
41static __attribute__((noreturn))
42void format(void)
43{
44 fprintf(stderr,
45 "Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n");
46 exit(2);
47}
48
49static void display_openssl_errors(int l)
50{
51 const char *file;
52 char buf[120];
53 int e, line;
54
55 if (ERR_peek_error() == 0)
56 return;
57 fprintf(stderr, "At main.c:%d:\n", l);
58
59 while ((e = ERR_get_error_line(&file, &line))) {
60 ERR_error_string(e, buf);
61 fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line);
62 }
63}
64
65static void drain_openssl_errors(void)
66{
67 const char *file;
68 int line;
69
70 if (ERR_peek_error() == 0)
71 return;
72 while (ERR_get_error_line(&file, &line)) {}
73}
74
75#define ERR(cond, fmt, ...) \
76 do { \
77 bool __cond = (cond); \
78 display_openssl_errors(__LINE__); \
79 if (__cond) { \
80 err(1, fmt, ## __VA_ARGS__); \
81 } \
82 } while(0)
83
84static const char *key_pass;
85
86static int pem_pw_cb(char *buf, int len, int w, void *v)
87{
88 int pwlen;
89
90 if (!key_pass)
91 return -1;
92
93 pwlen = strlen(key_pass);
94 if (pwlen >= len)
95 return -1;
96
97 strcpy(buf, key_pass);
98
99 /* If it's wrong, don't keep trying it. */
100 key_pass = NULL;
101
102 return pwlen;
103}
104
105int main(int argc, char **argv)
106{
107 struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 };
108 char *hash_algo = NULL;
109 char *private_key_name, *x509_name, *module_name, *dest_name;
110 bool save_cms = false, replace_orig;
111 bool sign_only = false;
112 unsigned char buf[4096];
113 unsigned long module_size, cms_size;
114 unsigned int use_keyid = 0, use_signed_attrs = CMS_NOATTR;
115 const EVP_MD *digest_algo;
116 EVP_PKEY *private_key;
117 CMS_ContentInfo *cms;
118 X509 *x509;
119 BIO *b, *bd = NULL, *bm;
120 int opt, n;
121
122 OpenSSL_add_all_algorithms();
123 ERR_load_crypto_strings();
124 ERR_clear_error();
125
126 key_pass = getenv("KBUILD_SIGN_PIN");
127
128 do {
129 opt = getopt(argc, argv, "dpk");
130 switch (opt) {
131 case 'p': save_cms = true; break;
132 case 'd': sign_only = true; save_cms = true; break;
133 case 'k': use_keyid = CMS_USE_KEYID; break;
134 case -1: break;
135 default: format();
136 }
137 } while (opt != -1);
138
139 argc -= optind;
140 argv += optind;
141 if (argc < 4 || argc > 5)
142 format();
143
144 hash_algo = argv[0];
145 private_key_name = argv[1];
146 x509_name = argv[2];
147 module_name = argv[3];
148 if (argc == 5) {
149 dest_name = argv[4];
150 replace_orig = false;
151 } else {
152 ERR(asprintf(&dest_name, "%s.~signed~", module_name) < 0,
153 "asprintf");
154 replace_orig = true;
155 }
156
157 /* Read the private key and the X.509 cert the PKCS#7 message
158 * will point to.
159 */
160 if (!strncmp(private_key_name, "pkcs11:", 7)) {
161 ENGINE *e;
162
163 ENGINE_load_builtin_engines();
164 drain_openssl_errors();
165 e = ENGINE_by_id("pkcs11");
166 ERR(!e, "Load PKCS#11 ENGINE");
167 if (ENGINE_init(e))
168 drain_openssl_errors();
169 else
170 ERR(1, "ENGINE_init");
171 if (key_pass)
172 ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN");
173 private_key = ENGINE_load_private_key(e, private_key_name, NULL,
174 NULL);
175 ERR(!private_key, "%s", private_key_name);
176 } else {
177 b = BIO_new_file(private_key_name, "rb");
178 ERR(!b, "%s", private_key_name);
179 private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, NULL);
180 ERR(!private_key, "%s", private_key_name);
181 BIO_free(b);
182 }
183
184 b = BIO_new_file(x509_name, "rb");
185 ERR(!b, "%s", x509_name);
186 x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */
187 if (!x509) {
188 ERR(BIO_reset(b) != 1, "%s", x509_name);
189 x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); /* PEM encoded X.509 */
190 if (x509)
191 drain_openssl_errors();
192 }
193 BIO_free(b);
194 ERR(!x509, "%s", x509_name);
195
196 /* Open the destination file now so that we can shovel the module data
197 * across as we read it.
198 */
199 if (!sign_only) {
200 bd = BIO_new_file(dest_name, "wb");
201 ERR(!bd, "%s", dest_name);
202 }
203
204 /* Digest the module data. */
205 OpenSSL_add_all_digests();
206 display_openssl_errors(__LINE__);
207 digest_algo = EVP_get_digestbyname(hash_algo);
208 ERR(!digest_algo, "EVP_get_digestbyname");
209
210 bm = BIO_new_file(module_name, "rb");
211 ERR(!bm, "%s", module_name);
212
213 /* Load the CMS message from the digest buffer. */
214 cms = CMS_sign(NULL, NULL, NULL, NULL,
215 CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED | CMS_STREAM);
216 ERR(!cms, "CMS_sign");
217
218 ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo,
219 CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP |
220 use_keyid | use_signed_attrs),
221 "CMS_sign_add_signer");
222 ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0,
223 "CMS_final");
224
225 if (save_cms) {
226 char *cms_name;
227
228 ERR(asprintf(&cms_name, "%s.p7s", module_name) < 0, "asprintf");
229 b = BIO_new_file(cms_name, "wb");
230 ERR(!b, "%s", cms_name);
231 ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0, "%s", cms_name);
232 BIO_free(b);
233 }
234
235 if (sign_only)
236 return 0;
237
238 /* Append the marker and the PKCS#7 message to the destination file */
239 ERR(BIO_reset(bm) < 0, "%s", module_name);
240 while ((n = BIO_read(bm, buf, sizeof(buf))),
241 n > 0) {
242 ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name);
243 }
244 ERR(n < 0, "%s", module_name);
245 module_size = BIO_number_written(bd);
246
247 ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name);
248 cms_size = BIO_number_written(bd) - module_size;
249 sig_info.sig_len = htonl(cms_size);
250 ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name);
251 ERR(BIO_write(bd, magic_number, sizeof(magic_number) - 1) < 0, "%s", dest_name);
252
253 ERR(BIO_free(bd) < 0, "%s", dest_name);
254
255 /* Finally, if we're signing in place, replace the original. */
256 if (replace_orig)
257 ERR(rename(dest_name, module_name) < 0, "%s", dest_name);
258
259 return 0;
260}