Commit | Line | Data |
---|---|---|
1cac41cb MB |
1 | /* |
2 | * Utility functions called from fips_fmp_hmac.sh. | |
3 | * | |
4 | * executed during Kernel build | |
5 | * | |
6 | * Copyright (c) 2014 Samsung Electronics | |
7 | * | |
8 | */ | |
9 | ||
10 | #include <stdio.h> | |
11 | #include <stdlib.h> | |
12 | #include <string.h> | |
13 | ||
14 | #define MAX_SIZE 0x100000 | |
15 | ||
16 | int update_fmp_hmac(const char *vmlinux_path, const char *hmac_path, unsigned long offset); | |
17 | int collect_fmp_bytes(const char *in_file, const char *section_name, unsigned long offset, | |
18 | unsigned long size, const char *out_file); | |
19 | ||
20 | int main(int argc, char **argv) | |
21 | { | |
22 | if (argc < 2) { | |
23 | printf("\nUsage : \n"); | |
24 | printf("fips_fmp_utils -u vmlinux_file hmac_file offset"); | |
25 | printf("fips_fmp_utils -g vmlinux_file section_name offset size out_file"); | |
26 | printf("\n"); | |
27 | ||
28 | return -1; | |
29 | } | |
30 | ||
31 | if (!strncmp("-u", argv[1], sizeof("-u"))) { | |
32 | unsigned long offset = 0; | |
33 | unsigned char *vmlinux_file = NULL; | |
34 | unsigned char *hmac_file = NULL; | |
35 | ||
36 | if (argc != 5) { | |
37 | printf("\nUsage : \n"); | |
38 | printf("fips_fmp_utils -u vmlinux_file hmac_file offset"); | |
39 | printf("\n"); | |
40 | ||
41 | return -1; | |
42 | } | |
43 | ||
44 | vmlinux_file = argv[2]; | |
45 | hmac_file = argv[3]; | |
46 | offset = atol(argv[4]); | |
47 | ||
48 | if (!vmlinux_file || !hmac_file || !offset) { | |
49 | printf ("./fips_fmp_utils -u vmlinux_file hmac_file offset"); | |
50 | return -1; | |
51 | } | |
52 | ||
53 | return update_fmp_hmac(vmlinux_file, hmac_file, offset); | |
54 | } else if (!strncmp("-g", argv[1], sizeof("-g"))) { | |
55 | const char *in_file = NULL; | |
56 | const char *section_name = NULL; | |
57 | unsigned long offset = 0; | |
58 | unsigned long size = 0; | |
59 | const char *out_file = NULL; | |
60 | ||
61 | if (argc != 7) { | |
62 | printf("\nUsage : \n"); | |
63 | printf("./fips_fmp_utils -g vmlinux_file section_name offset size out_file"); | |
64 | printf("\n"); | |
65 | ||
66 | return -1; | |
67 | } | |
68 | ||
69 | in_file = argv[2]; | |
70 | section_name = argv[3]; | |
71 | offset = atol(argv[4]); | |
72 | size = atol(argv[5]); | |
73 | out_file = argv[6]; | |
74 | ||
75 | if (!in_file || !section_name || !offset || !size || !out_file) { | |
76 | printf("./fips_fmp_utils -g vmlinux_file section_name offset size out_file"); | |
77 | return -1; | |
78 | } | |
79 | ||
80 | if (size > MAX_SIZE) { | |
81 | printf("Fail fips_fmp_utils due to invalid size: %ld\n", size); | |
82 | return -1; | |
83 | } | |
84 | ||
85 | return collect_fmp_bytes(in_file, section_name, offset, size, out_file); | |
86 | } else { | |
87 | printf("\nUsage : \n"); | |
88 | printf("fips_fmp_utils -u vmlinux_file hmac_file offset"); | |
89 | printf("fips_fmp_utils -g vmlinux_file section_name offset size out_file"); | |
90 | printf("\n"); | |
91 | } | |
92 | ||
93 | return -1; | |
94 | } | |
95 | ||
96 | /* | |
97 | * Given a vmlinux file, dumps "size" bytes from given "offset" to output file | |
98 | * in_file : absolute path to vmlinux file | |
99 | * section_name : Used only for printing / debugging | |
100 | * offset : offset in file from where to dump bytes | |
101 | * size : how many bytes to dump | |
102 | * out_file : Output file, where to dump bytes. | |
103 | * Open in append mode, to keep previous bytes, if present | |
104 | * Caller need to clean up before 1st call | |
105 | * | |
106 | * Returns 0, if success | |
107 | * -1, if error | |
108 | */ | |
109 | ||
110 | int collect_fmp_bytes(const char *in_file, const char *section_name, unsigned long offset, | |
111 | unsigned long size, const char *out_file) | |
112 | { | |
113 | FILE *in_fp = NULL; | |
114 | FILE *out_fp = NULL; | |
115 | unsigned int i = 0; | |
116 | unsigned char data = 0; | |
117 | ||
118 | if (!in_file || !section_name || !offset || !size || !out_file) { | |
119 | printf ("collect_fmp_bytes : Invalid arguments"); | |
120 | return -1; | |
121 | } | |
122 | ||
123 | printf("Section : %s\n", section_name); | |
124 | ||
125 | in_fp = fopen(in_file, "r"); | |
126 | if (!in_fp) { | |
127 | printf("Unable to open file : %s", in_file); | |
128 | return -1; | |
129 | } | |
130 | ||
131 | if (fseek(in_fp, offset, SEEK_SET) != 0) { | |
132 | printf ("Unable to seek file : %s", in_file); | |
133 | goto err_fseek; | |
134 | } | |
135 | ||
136 | out_fp = fopen(out_file, "ab"); | |
137 | if (!out_fp) { | |
138 | printf ("Unable to open file : %s", out_file); | |
139 | goto err_open_out_fp; | |
140 | } | |
141 | ||
142 | if (size > MAX_SIZE) { | |
143 | printf("Fail fips_fmp_utils due to invalid size: %ld\n", size); | |
144 | goto err; | |
145 | } | |
146 | ||
147 | if (size > MAX_SIZE) { | |
148 | printf("Fail fips_fmp_utils due to invalid size: %ld\n", size); | |
149 | return -1; | |
150 | } | |
151 | ||
152 | for (i = 1; i <= size; i++) { | |
153 | if ( 1 != fread (&data, sizeof(unsigned char), 1, in_fp)) { | |
154 | printf("Unable to read 1 byte from file : %s", in_file); | |
155 | goto err; | |
156 | } | |
157 | ||
158 | printf ("%02x ", data); | |
159 | if (1 != fwrite (&data, 1, 1, out_fp)) { | |
160 | printf("Unable to write 1 byte to file : %s", out_file); | |
161 | goto err; | |
162 | } | |
163 | ||
164 | if (!(i % 16)) | |
165 | printf("\n"); | |
166 | } | |
167 | ||
168 | fclose(out_fp); | |
169 | fclose(in_fp); | |
170 | ||
171 | return 0; | |
172 | err: | |
173 | fclose(out_fp); | |
174 | err_open_out_fp: | |
175 | err_fseek: | |
176 | fclose(in_fp); | |
177 | return -1; | |
178 | } | |
179 | ||
180 | #define SHA256_DIGEST_SIZE 32 | |
181 | ||
182 | /* | |
183 | * Given a vmlinux file, overwrites bytes at given offset with hmac bytes, available in | |
184 | * hmac file. | |
185 | * Return 0, if Success | |
186 | * -1, if Error | |
187 | */ | |
188 | int update_fmp_hmac(const char *vmlinux_path, const char *hmac_path, unsigned long offset) | |
189 | { | |
190 | FILE *vmlinux_fp = NULL; | |
191 | FILE *hmac_fp = NULL; | |
192 | int i = 0, j = 0; | |
193 | unsigned char hmac[SHA256_DIGEST_SIZE]; | |
194 | ||
195 | if (!vmlinux_path || !hmac_path || !offset) { | |
196 | printf("FIPS update_fmp_hmac : Invalid Params"); | |
197 | return -1; | |
198 | } | |
199 | ||
200 | vmlinux_fp = fopen(vmlinux_path, "r+b"); | |
201 | if (!vmlinux_fp) { | |
202 | printf("Unable to open vmlinux file "); | |
203 | return -1; | |
204 | } | |
205 | ||
206 | hmac_fp = fopen(hmac_path, "rb"); | |
207 | if (!hmac_fp) { | |
208 | printf("Unable to open hmac file "); | |
209 | goto err_open_hmac_fp; | |
210 | } | |
211 | ||
212 | if (SHA256_DIGEST_SIZE != fread(&hmac, sizeof(unsigned char), SHA256_DIGEST_SIZE, hmac_fp)) { | |
213 | printf("Unable to read %d bytes from hmac file", SHA256_DIGEST_SIZE); | |
214 | goto err; | |
215 | } | |
216 | ||
217 | if (fseek(vmlinux_fp, offset, SEEK_SET) != 0) { | |
218 | printf("Unable to seek into vmlinux file."); | |
219 | goto err; | |
220 | } | |
221 | ||
222 | if (SHA256_DIGEST_SIZE != fwrite (hmac, sizeof(unsigned char), SHA256_DIGEST_SIZE, vmlinux_fp)) { | |
223 | printf("Unable to write %d byte into vmlinux", SHA256_DIGEST_SIZE); | |
224 | goto err; | |
225 | } | |
226 | ||
227 | fclose(vmlinux_fp); | |
228 | fclose(hmac_fp); | |
229 | ||
230 | return 0; | |
231 | ||
232 | err: | |
233 | fclose(hmac_fp); | |
234 | err_open_hmac_fp: | |
235 | fclose(vmlinux_fp); | |
236 | return -1; | |
237 | } |