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
|
/*
* Copyright 2014 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <stdint.h>
#include <string.h>
#include "gbb_header.h"
static int is_null_terminated(const char *s, int len)
{
len--;
s += len;
while (len-- >= 0)
if (!*s--)
return 1;
return 0;
}
static inline uint32_t max(uint32_t a, uint32_t b)
{
return a > b ? a : b;
}
int futil_looks_like_gbb(GoogleBinaryBlockHeader *gbb, uint32_t len)
{
if (memcmp(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE))
return 0;
if (gbb->major_version > GBB_MAJOR_VER)
return 0;
if (sizeof(GoogleBinaryBlockHeader) > len)
return 0;
/* close enough */
return 1;
}
int futil_valid_gbb_header(GoogleBinaryBlockHeader *gbb, uint32_t len,
uint32_t *maxlen_ptr)
{
if (memcmp(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE))
return 0;
if (gbb->major_version != GBB_MAJOR_VER)
return 0;
/* Check limits first, to help identify problems */
if (maxlen_ptr) {
uint32_t maxlen = gbb->header_size;
maxlen = max(maxlen,
gbb->hwid_offset + gbb->hwid_size);
maxlen = max(maxlen,
gbb->rootkey_offset + gbb->rootkey_size);
maxlen = max(maxlen,
gbb->bmpfv_offset + gbb->bmpfv_size);
maxlen = max(maxlen,
gbb->recovery_key_offset + gbb->recovery_key_size);
*maxlen_ptr = maxlen;
}
if (gbb->header_size != GBB_HEADER_SIZE || gbb->header_size > len)
return 0;
if (gbb->hwid_offset < GBB_HEADER_SIZE)
return 0;
if (gbb->hwid_offset + gbb->hwid_size > len)
return 0;
if (gbb->hwid_size) {
const char *s = (const char *)
((uint8_t *)gbb + gbb->hwid_offset);
if (!is_null_terminated(s, gbb->hwid_size))
return 0;
}
if (gbb->rootkey_offset < GBB_HEADER_SIZE)
return 0;
if (gbb->rootkey_offset + gbb->rootkey_size > len)
return 0;
if (gbb->bmpfv_offset < GBB_HEADER_SIZE)
return 0;
if (gbb->bmpfv_offset + gbb->bmpfv_size > len)
return 0;
if (gbb->recovery_key_offset < GBB_HEADER_SIZE)
return 0;
if (gbb->recovery_key_offset + gbb->recovery_key_size > len)
return 0;
/* Seems legit... */
return 1;
}
|