comparison common/binverify.c @ 771:2798f1869eee

(issue43) Add first draft of signature verification for GNU/Linux
author Andre Heinecke <andre.heinecke@intevation.de>
date Thu, 10 Jul 2014 19:15:22 +0200
parents be30d50bc4f0
children 44fa5de02b52
comparison
equal deleted inserted replaced
770:7861950f7637 771:2798f1869eee
17 #include "pubkey-test.h" 17 #include "pubkey-test.h"
18 #endif 18 #endif
19 19
20 bin_verify_result 20 bin_verify_result
21 verify_binary(const char *filename, size_t name_len) { 21 verify_binary(const char *filename, size_t name_len) {
22 if (!filename || !name_len)
23 return VerifyUnknownError;
22 #ifdef WIN32 24 #ifdef WIN32
23 return verify_binary_win(filename, name_len); 25 return verify_binary_win(filename, name_len);
24 #else 26 #else
25 /* TODO */ 27 return verify_binary_linux(filename, name_len);
26 if (filename && name_len)
27 return VerifyValid;
28 return VerifyUnknownError;
29 #endif 28 #endif
30 } 29 }
31 30
32 #ifdef WIN32 31 #ifdef WIN32
33 32
222 { 221 {
223 CryptMsgClose(hMsg); 222 CryptMsgClose(hMsg);
224 } 223 }
225 return retval; 224 return retval;
226 } 225 }
226 #else /* WIN32 */
227
228 #include "listutil.h"
229
230 #pragma GCC diagnostic ignored "-Wconversion"
231 /* Polarssl mh.h contains a conversion which gcc warns about */
232 #include <polarssl/pk.h>
233 #include <polarssl/base64.h>
234 #include <polarssl/sha256.h>
235 #pragma GCC diagnostic pop
236
237 bin_verify_result
238 verify_binary_linux(const char *filename, size_t name_len)
239 {
240 int ret = -1;
241 const size_t sig_b64_size = TRUSTBRIDGE_RSA_KEY_SIZE / 8 * 4 / 3;
242 char *data = NULL,
243 signature_b64[sig_b64_size + 1];
244 size_t data_size = 0,
245 sig_size = TRUSTBRIDGE_RSA_KEY_SIZE / 8;
246 unsigned char signature[sig_size],
247 hash[32];
248
249 bin_verify_result retval = VerifyUnknownError;
250 pk_context pub_key_ctx;
251
252 if (strnlen(filename, name_len + 1) != name_len || name_len == 0)
253 {
254 ERRORPRINTF ("Invalid call to verify_binary_linux\n");
255 return VerifyUnknownError;
256 }
257
258 ret = read_file(filename, &data, &data_size, MAX_VALID_BIN_SIZE);
259
260 if (ret != 0)
261 {
262 ERRORPRINTF ("Read file failed with error: %i\n", ret);
263 return VerifyReadFailed;
264 }
265
266 /* Fetch the signature from the end of data */
267 if (data_size < sig_b64_size + 4)
268 {
269 ERRORPRINTF ("File to small to contain a signature.\n");
270 retval = VerifyInvalidSignature;
271 goto done;
272 }
273
274 if (data[data_size - sig_b64_size - 1] != ':' ||
275 data[data_size - sig_b64_size - 2] != 'S' ||
276 data[data_size - sig_b64_size - 3] != '\n'||
277 data[data_size - sig_b64_size - 4] != '\r')
278 {
279 ERRORPRINTF ("Failed to find valid signature line.\n");
280 retval = VerifyInvalidSignature;
281 goto done;
282 }
283
284 strncpy(signature_b64, data - sig_b64_size, sig_b64_size);
285 signature_b64[sig_b64_size] = '\0';
286
287 ret = base64_decode(signature, &sig_size,
288 (unsigned char *)signature_b64, sig_b64_size);
289
290 if (ret != 0 || sig_size != TRUSTBRIDGE_RSA_KEY_SIZE / 8)
291 {
292 goto done;
293 }
294
295 /* Hash is calculated over the data without the signature at the end. */
296 sha256((unsigned char *)data, data_size - sig_b64_size - 4, hash, 0);
297
298 pk_init(&pub_key_ctx);
299
300 ret = pk_parse_public_key(&pub_key_ctx, public_key_codesign_pem,
301 public_key_codesign_pem_size);
302 if (ret != 0)
303 {
304 ERRORPRINTF ("pk_parse_public_key failed with -0x%04x\n\n", -ret);
305 pk_free(&pub_key_ctx);
306 return VerifyUnknownError;
307 }
308
309 ret = pk_verify(&pub_key_ctx, POLARSSL_MD_SHA256, hash, 0,
310 signature, sig_size);
311
312 if (ret != 0)
313 {
314 ERRORPRINTF ("pk_verify failed with -0x%04x\n\n", -ret);
315 }
316 pk_free(&pub_key_ctx);
317
318 return VerifyValid;
319
320 done:
321 xfree (data);
322 return retval;
323 }
324
227 #endif /* WIN32 */ 325 #endif /* WIN32 */

http://wald.intevation.org/projects/trustbridge/