diff options
Diffstat (limited to 'crypto/asymmetric_keys/verify_pefile.c')
-rw-r--r-- | crypto/asymmetric_keys/verify_pefile.c | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 79175e6ea0b2..2421f46184ce 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c | |||
@@ -128,6 +128,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf, | |||
128 | { | 128 | { |
129 | struct win_certificate wrapper; | 129 | struct win_certificate wrapper; |
130 | const u8 *pkcs7; | 130 | const u8 *pkcs7; |
131 | unsigned len; | ||
131 | 132 | ||
132 | if (ctx->sig_len < sizeof(wrapper)) { | 133 | if (ctx->sig_len < sizeof(wrapper)) { |
133 | pr_debug("Signature wrapper too short\n"); | 134 | pr_debug("Signature wrapper too short\n"); |
@@ -154,33 +155,49 @@ static int pefile_strip_sig_wrapper(const void *pebuf, | |||
154 | return -ENOTSUPP; | 155 | return -ENOTSUPP; |
155 | } | 156 | } |
156 | 157 | ||
157 | /* Looks like actual pkcs signature length is in wrapper->length. | 158 | /* It looks like the pkcs signature length in wrapper->length and the |
158 | * size obtained from data dir entries lists the total size of | 159 | * size obtained from the data dir entries, which lists the total size |
159 | * certificate table which is also aligned to octawrod boundary. | 160 | * of certificate table, are both aligned to an octaword boundary, so |
160 | * | 161 | * we may have to deal with some padding. |
161 | * So set signature length field appropriately. | ||
162 | */ | 162 | */ |
163 | ctx->sig_len = wrapper.length; | 163 | ctx->sig_len = wrapper.length; |
164 | ctx->sig_offset += sizeof(wrapper); | 164 | ctx->sig_offset += sizeof(wrapper); |
165 | ctx->sig_len -= sizeof(wrapper); | 165 | ctx->sig_len -= sizeof(wrapper); |
166 | if (ctx->sig_len == 0) { | 166 | if (ctx->sig_len < 4) { |
167 | pr_debug("Signature data missing\n"); | 167 | pr_debug("Signature data missing\n"); |
168 | return -EKEYREJECTED; | 168 | return -EKEYREJECTED; |
169 | } | 169 | } |
170 | 170 | ||
171 | /* What's left should a PKCS#7 cert */ | 171 | /* What's left should be a PKCS#7 cert */ |
172 | pkcs7 = pebuf + ctx->sig_offset; | 172 | pkcs7 = pebuf + ctx->sig_offset; |
173 | if (pkcs7[0] == (ASN1_CONS_BIT | ASN1_SEQ)) { | 173 | if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ)) |
174 | if (pkcs7[1] == 0x82 && | 174 | goto not_pkcs7; |
175 | pkcs7[2] == (((ctx->sig_len - 4) >> 8) & 0xff) && | 175 | |
176 | pkcs7[3] == ((ctx->sig_len - 4) & 0xff)) | 176 | switch (pkcs7[1]) { |
177 | return 0; | 177 | case 0 ... 0x7f: |
178 | if (pkcs7[1] == 0x80) | 178 | len = pkcs7[1] + 2; |
179 | return 0; | 179 | goto check_len; |
180 | if (pkcs7[1] > 0x82) | 180 | case ASN1_INDEFINITE_LENGTH: |
181 | return -EMSGSIZE; | 181 | return 0; |
182 | case 0x81: | ||
183 | len = pkcs7[2] + 3; | ||
184 | goto check_len; | ||
185 | case 0x82: | ||
186 | len = ((pkcs7[2] << 8) | pkcs7[3]) + 4; | ||
187 | goto check_len; | ||
188 | case 0x83 ... 0xff: | ||
189 | return -EMSGSIZE; | ||
190 | default: | ||
191 | goto not_pkcs7; | ||
182 | } | 192 | } |
183 | 193 | ||
194 | check_len: | ||
195 | if (len <= ctx->sig_len) { | ||
196 | /* There may be padding */ | ||
197 | ctx->sig_len = len; | ||
198 | return 0; | ||
199 | } | ||
200 | not_pkcs7: | ||
184 | pr_debug("Signature data not PKCS#7\n"); | 201 | pr_debug("Signature data not PKCS#7\n"); |
185 | return -ELIBBAD; | 202 | return -ELIBBAD; |
186 | } | 203 | } |