~ubuntu-branches/ubuntu/utopic/clamav/utopic-security

« back to all changes in this revision

Viewing changes to libclamav/asn1.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman
  • Date: 2014-02-01 11:06:17 UTC
  • mfrom: (0.35.37 sid)
  • Revision ID: package-import@ubuntu.com-20140201110617-33h2xxk09dep0ui4
Tags: 0.98.1+dfsg-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - Drop build-dep on electric-fence (in Universe)
  - Add apparmor profiles for clamd and freshclam along with maintainer
    script changes
  - Add autopkgtest

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2011 Sourcefire, Inc.
 
3
 *
 
4
 *  Authors: aCaB
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License version 2 as
 
8
 *  published by the Free Software Foundation.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
18
 *  MA 02110-1301, USA.
 
19
 */
 
20
 
 
21
#if HAVE_CONFIG_H
 
22
#include "clamav-config.h"
 
23
#endif
 
24
 
 
25
#include <time.h>
 
26
 
 
27
#include "asn1.h"
 
28
#include "sha1.h"
 
29
#include "md5.h"
 
30
#include "bignum.h"
 
31
#include "matcher-hash.h"
 
32
 
 
33
/* --------------------------------------------------------------------------- OIDS */
 
34
#define OID_1_3_14_3_2_26 "\x2b\x0e\x03\x02\x1a"
 
35
#define OID_sha1 OID_1_3_14_3_2_26
 
36
 
 
37
#define OID_1_3_14_3_2_29 "\x2b\x0e\x03\x02\x1d"
 
38
#define OID_sha1WithRSA OID_1_3_14_3_2_29
 
39
 
 
40
#define OID_1_2_840_113549_1_1_1 "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01"
 
41
#define OID_rsaEncryption OID_1_2_840_113549_1_1_1
 
42
 
 
43
#define OID_1_2_840_113549_1_1_4 "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04"
 
44
#define OID_md5WithRSAEncryption OID_1_2_840_113549_1_1_4
 
45
 
 
46
#define OID_1_2_840_113549_1_1_5 "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05"
 
47
#define OID_sha1WithRSAEncryption OID_1_2_840_113549_1_1_5
 
48
 
 
49
#define OID_1_2_840_113549_1_7_1 "\x2a\x86\x48\x86\xf7\x0d\x01\x07\x01"
 
50
#define OID_pkcs7_data OID_1_2_840_113549_1_7_1
 
51
 
 
52
#define OID_1_2_840_113549_1_7_2 "\x2a\x86\x48\x86\xf7\x0d\x01\x07\x02"
 
53
#define OID_signedData OID_1_2_840_113549_1_7_2
 
54
 
 
55
#define OID_1_2_840_113549_1_9_3 "\x2a\x86\x48\x86\xf7\x0d\x01\x09\x03"
 
56
#define OID_contentType OID_1_2_840_113549_1_9_3
 
57
 
 
58
#define OID_1_2_840_113549_1_9_4 "\x2a\x86\x48\x86\xf7\x0d\x01\x09\x04"
 
59
#define OID_messageDigest OID_1_2_840_113549_1_9_4
 
60
 
 
61
#define OID_1_2_840_113549_1_9_5 "\x2a\x86\x48\x86\xf7\x0d\x01\x09\x05"
 
62
#define OID_signingTime OID_1_2_840_113549_1_9_5
 
63
 
 
64
#define OID_1_2_840_113549_2_5 "\x2a\x86\x48\x86\xf7\x0d\x02\x05"
 
65
#define OID_md5 OID_1_2_840_113549_2_5
 
66
 
 
67
#define OID_1_2_840_113549_1_9_6 "\x2a\x86\x48\x86\xf7\x0d\x01\x09\x06"
 
68
#define OID_countersignature OID_1_2_840_113549_1_9_6
 
69
 
 
70
 
 
71
#define OID_1_3_6_1_4_1_311_2_1_4 "\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x04"
 
72
#define OID_SPC_INDIRECT_DATA_OBJID OID_1_3_6_1_4_1_311_2_1_4
 
73
 
 
74
#define OID_1_3_6_1_4_1_311_2_1_15 "\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x0f"
 
75
#define OID_SPC_PE_IMAGE_DATA_OBJID OID_1_3_6_1_4_1_311_2_1_15
 
76
 
 
77
#define OID_1_3_6_1_4_1_311_2_1_25 "\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x19"
 
78
#define OID_SPC_CAB_DATA_OBJID OID_1_3_6_1_4_1_311_2_1_25
 
79
 
 
80
#define OID_1_3_6_1_4_1_311_10_1 "\x2b\x06\x01\x04\x01\x82\x37\x0a\x01"
 
81
#define OID_szOID_CTL OID_1_3_6_1_4_1_311_10_1
 
82
 
 
83
#define OID_1_3_6_1_4_1_311_12_1_1 "\x2b\x06\x01\x04\x01\x82\x37\x0c\x01\x01"
 
84
#define OID_szOID_CATALOG_LIST OID_1_3_6_1_4_1_311_12_1_1
 
85
 
 
86
#define OID_1_3_6_1_4_1_311_12_1_2 "\x2b\x06\x01\x04\x01\x82\x37\x0c\x01\x02"
 
87
#define OID_szOID_CATALOG_LIST_MEMBER OID_1_3_6_1_4_1_311_12_1_2
 
88
 
 
89
#define lenof(x) (sizeof((x))-1)
 
90
/* --------------------------------------------------------------------------- OIDS */
 
91
 
 
92
struct cli_asn1 {
 
93
    uint8_t type;
 
94
    unsigned int size;
 
95
    const void *content;
 
96
    const void *next;
 
97
};
 
98
 
 
99
static int map_sha1(fmap_t *map, const void *data, unsigned int len, uint8_t sha1[SHA1_HASH_SIZE]) {
 
100
    SHA1Context ctx;
 
101
    if(!fmap_need_ptr_once(map, data, len)) {
 
102
        cli_dbgmsg("map_sha1: failed to read hash data\n");
 
103
        return 1;
 
104
    }
 
105
    SHA1Init(&ctx);
 
106
    while(len) {
 
107
        unsigned int todo = MIN(len, map->pgsz);
 
108
        SHA1Update(&ctx, data, todo);
 
109
        data = (uint8_t *)data + todo;
 
110
        len -= todo;
 
111
    }
 
112
    SHA1Final(&ctx, sha1);
 
113
    return 0;
 
114
}
 
115
 
 
116
static int map_md5(fmap_t *map, const void *data, unsigned int len, uint8_t *md5) {
 
117
    cli_md5_ctx ctx;
 
118
    if(!fmap_need_ptr_once(map, data, len)) {
 
119
        cli_dbgmsg("map_md5: failed to read hash data\n");
 
120
        return 1;
 
121
    }
 
122
    cli_md5_init(&ctx);
 
123
    while(len) {
 
124
        unsigned int todo = MIN(len, map->pgsz);
 
125
        cli_md5_update(&ctx, data, len);
 
126
        data = (uint8_t *)data + todo;
 
127
        len -= todo;
 
128
    }
 
129
    cli_md5_final(md5, &ctx);
 
130
    return 0;
 
131
}
 
132
 
 
133
 
 
134
static int asn1_get_obj(fmap_t *map, const void *asn1data, unsigned int *asn1len, struct cli_asn1 *obj) {
 
135
    unsigned int asn1_sz = *asn1len;
 
136
    unsigned int readbytes = MIN(6, asn1_sz), i;
 
137
    const uint8_t *data;
 
138
 
 
139
    if(asn1_sz < 2) {
 
140
        cli_dbgmsg("asn1_get_obj: insufficient data length\n");
 
141
        return 1;
 
142
    }
 
143
    data = fmap_need_ptr_once(map, asn1data, readbytes);
 
144
    if(!data) {
 
145
        cli_dbgmsg("asn1_get_obj: obj out of file\n");
 
146
        return 1;
 
147
    }
 
148
 
 
149
    obj->type = data[0];
 
150
    i = data[1];
 
151
    data+=2;
 
152
    if(i & 0x80) {
 
153
        if(i == 0x80) {
 
154
            /* Not allowed in DER */
 
155
            cli_dbgmsg("asn1_get_obj: unsupported indefinite length object\n");
 
156
            return 1;
 
157
        }
 
158
        i &= ~0x80;
 
159
        if(i > readbytes - 2) {
 
160
            cli_dbgmsg("asn1_get_obj: len octets overflow (or just too many)\n");
 
161
            return 1;
 
162
        }
 
163
        obj->size = 0;
 
164
        while(i--) {
 
165
            obj->size <<= 8;
 
166
            obj->size |= *data;
 
167
            data ++;
 
168
        }
 
169
    } else
 
170
        obj->size = i;
 
171
 
 
172
    asn1_sz -= data - (uint8_t *)asn1data;
 
173
    if(obj->size > asn1_sz) {
 
174
        cli_dbgmsg("asn1_get_obj: content overflow\n");
 
175
        return 1;
 
176
    }
 
177
 
 
178
    obj->content = data;
 
179
    if(obj->size == asn1_sz)
 
180
        obj->next = NULL;
 
181
    else
 
182
        obj->next = data + obj->size;
 
183
    *asn1len = asn1_sz - obj->size;
 
184
    return 0;
 
185
}
 
186
 
 
187
static int asn1_expect_objtype(fmap_t *map, const void *asn1data, unsigned int *asn1len, struct cli_asn1 *obj, uint8_t type) {
 
188
    int ret = asn1_get_obj(map, asn1data, asn1len, obj);
 
189
    if(ret)
 
190
        return ret;
 
191
    if(obj->type != type) {
 
192
        cli_dbgmsg("asn1_expect_objtype: expected type %02x, got %02x\n", type, obj->type);
 
193
        return 1;
 
194
    }
 
195
    return 0;
 
196
}
 
197
 
 
198
static int asn1_expect_obj(fmap_t *map, const void **asn1data, unsigned int *asn1len, uint8_t type, unsigned int size, const void *content) {
 
199
    struct cli_asn1 obj;
 
200
    int ret = asn1_expect_objtype(map, *asn1data, asn1len, &obj, type);
 
201
    if(ret)
 
202
        return ret;
 
203
    if(obj.size != size) {
 
204
        cli_dbgmsg("asn1_expect_obj: expected size %u, got %u\n", size, obj.size);
 
205
        return 1;
 
206
    }
 
207
    if(size) {
 
208
        if(!fmap_need_ptr_once(map, obj.content, size)) {
 
209
            cli_dbgmsg("asn1_expect_obj: failed to read content\n");
 
210
            return 1;
 
211
        }
 
212
        if(memcmp(obj.content, content, size)) {
 
213
            cli_dbgmsg("asn1_expect_obj: content mismatch\n");
 
214
            return 1;
 
215
        }
 
216
    }
 
217
    *asn1data = obj.next;
 
218
    return 0;
 
219
}
 
220
 
 
221
static int asn1_expect_algo(fmap_t *map, const void **asn1data, unsigned int *asn1len, unsigned int algo_size, const void *algo) {
 
222
    struct cli_asn1 obj;
 
223
    unsigned int avail;
 
224
    int ret;
 
225
    if((ret = asn1_expect_objtype(map, *asn1data, asn1len, &obj, 0x30))) /* SEQUENCE */
 
226
        return ret;
 
227
    avail = obj.size;
 
228
    *asn1data = obj.next;
 
229
 
 
230
    if((ret = asn1_expect_obj(map, &obj.content, &avail, 0x06, algo_size, algo))) /* ALGO */
 
231
        return ret;
 
232
    if(avail && (ret = asn1_expect_obj(map, &obj.content, &avail, 0x05, 0, NULL))) /* NULL */
 
233
        return ret;
 
234
    if(avail) {
 
235
        cli_dbgmsg("asn1_expect_algo: extra data found in SEQUENCE\n");
 
236
        return 1;
 
237
    }
 
238
    return 0;
 
239
}
 
240
 
 
241
 
 
242
static int asn1_expect_rsa(fmap_t *map, const void **asn1data, unsigned int *asn1len, cli_crt_hashtype *hashtype) {
 
243
    struct cli_asn1 obj;
 
244
    unsigned int avail;
 
245
    int ret;
 
246
    if((ret = asn1_expect_objtype(map, *asn1data, asn1len, &obj, 0x30))) /* SEQUENCE */
 
247
        return ret;
 
248
    avail = obj.size;
 
249
    *asn1data = obj.next;
 
250
 
 
251
    if(asn1_expect_objtype(map, obj.content, &avail, &obj, 0x06))
 
252
        return 1;
 
253
    if(obj.size != lenof(OID_sha1WithRSA) && obj.size != lenof(OID_sha1WithRSAEncryption)) { /* lenof(OID_sha1WithRSAEncryption) = lenof(OID_md5WithRSAEncryption) = 9 */
 
254
        cli_dbgmsg("asn1_expect_rsa: expecting OID with size 5 or 9, got %02x with size %u\n", obj.type, obj.size);
 
255
        return 1;
 
256
    }
 
257
    if(!fmap_need_ptr_once(map, obj.content, obj.size)) {
 
258
        cli_dbgmsg("asn1_expect_rsa: failed to read OID\n");
 
259
        return 1;
 
260
    }
 
261
    if(obj.size == lenof(OID_sha1WithRSA) && !memcmp(obj.content, OID_sha1WithRSA, lenof(OID_sha1WithRSA)))
 
262
        *hashtype = CLI_SHA1RSA; /* Obsolete sha1rsa 1.3.14.3.2.29 */
 
263
    else if(obj.size == lenof(OID_sha1WithRSAEncryption) && !memcmp(obj.content, OID_sha1WithRSAEncryption, lenof(OID_sha1WithRSAEncryption)))
 
264
        *hashtype = CLI_SHA1RSA; /* sha1withRSAEncryption 1.2.840.113549.1.1.5 */
 
265
    else if(obj.size == lenof(OID_md5WithRSAEncryption) && !memcmp(obj.content, OID_md5WithRSAEncryption, lenof(OID_md5WithRSAEncryption)))
 
266
        *hashtype = CLI_MD5RSA; /* md5withRSAEncryption 1.2.840.113549.1.1.4 */
 
267
    else {
 
268
        cli_dbgmsg("asn1_expect_rsa: OID mismatch\n");
 
269
        return 1;
 
270
    }
 
271
    if((ret = asn1_expect_obj(map, &obj.next, &avail, 0x05, 0, NULL))) /* NULL */
 
272
        return ret;
 
273
    if(avail) {
 
274
        cli_dbgmsg("asn1_expect_rsa: extra data found in SEQUENCE\n");
 
275
        return 1;
 
276
    }
 
277
    return 0;
 
278
}
 
279
 
 
280
static int asn1_getnum(const char *s) {
 
281
    if(s[0] < '0' || s[0] >'9' || s[1] < '0' || s[1] > '9') {
 
282
        cli_dbgmsg("asn1_getnum: expecting digits, found '%c%c'\n", s[0], s[1]);
 
283
        return -1;
 
284
    }
 
285
    return (s[0] - '0')*10 + (s[1] - '0');
 
286
}
 
287
 
 
288
static int asn1_get_time(fmap_t *map, const void **asn1data, unsigned int *size, time_t *tm) {
 
289
    struct cli_asn1 obj;
 
290
    int ret = asn1_get_obj(map, *asn1data, size, &obj);
 
291
    unsigned int len;
 
292
    char *ptr;
 
293
    struct tm t;
 
294
    int n;
 
295
 
 
296
    if(ret)
 
297
        return ret;
 
298
 
 
299
    if(obj.type == 0x17) /* UTCTime - YYMMDDHHMMSSZ */
 
300
        len = 13;
 
301
    else if(obj.type == 0x18) /* GeneralizedTime - YYYYMMDDHHMMSSZ */
 
302
        len = 15;
 
303
    else {
 
304
        cli_dbgmsg("asn1_get_time: expected UTCTime or GeneralizedTime, got %02x\n", obj.type);
 
305
        return 1;
 
306
    }
 
307
 
 
308
    if(!fmap_need_ptr_once(map, obj.content, len)) {
 
309
        cli_dbgmsg("asn1_get_time: failed to read content\n");
 
310
        return 1;
 
311
    }
 
312
 
 
313
    memset(&t, 0, sizeof(t));
 
314
    ptr = (char *)obj.content;
 
315
    if(obj.type == 0x18) {
 
316
        t.tm_year = asn1_getnum(ptr) * 100;
 
317
        if(t.tm_year < 0)
 
318
            return 1;
 
319
        n = asn1_getnum(ptr);
 
320
        if(n<0)
 
321
            return 1;
 
322
        t.tm_year += n;
 
323
        ptr+=4;
 
324
    } else {
 
325
        n = asn1_getnum(ptr);
 
326
        if(n<0)
 
327
            return 1;
 
328
        if(n>=50)
 
329
            t.tm_year = 1900 + n;
 
330
        else
 
331
            t.tm_year = 2000 + n;
 
332
        ptr += 2;
 
333
    }
 
334
    t.tm_year -= 1900;
 
335
    n = asn1_getnum(ptr);
 
336
    if(n<1 || n>12) {
 
337
        cli_dbgmsg("asn1_get_time: invalid month %u\n", n);
 
338
        return 1;
 
339
    }
 
340
    t.tm_mon = n - 1;
 
341
    ptr+=2;
 
342
 
 
343
    n = asn1_getnum(ptr);
 
344
    if(n<1 || n>31) {
 
345
        cli_dbgmsg("asn1_get_time: invalid day %u\n", n);
 
346
        return 1;
 
347
    }
 
348
    t.tm_mday = n;
 
349
    ptr+=2;
 
350
 
 
351
    n = asn1_getnum(ptr);
 
352
    if(n<0 || n>23) {
 
353
        cli_dbgmsg("asn1_get_time: invalid hour %u\n", n);
 
354
        return 1;
 
355
    }
 
356
    t.tm_hour = n;
 
357
    ptr+=2;
 
358
 
 
359
    n = asn1_getnum(ptr);
 
360
    if(n<0 || n>59) {
 
361
        cli_dbgmsg("asn1_get_time: invalid minute %u\n", n);
 
362
        return 1;
 
363
    }
 
364
    t.tm_min = n;
 
365
    ptr+=2;
 
366
 
 
367
    n = asn1_getnum(ptr);
 
368
    if(n<0 || n>59) {
 
369
        cli_dbgmsg("asn1_get_time: invalid second %u\n", n);
 
370
        return 1;
 
371
    }
 
372
    t.tm_sec = n;
 
373
    ptr+=2;
 
374
 
 
375
    if(*ptr != 'Z') {
 
376
        cli_dbgmsg("asn1_get_time: expected UTC time 'Z', got '%c'\n", *ptr);
 
377
        return 1;
 
378
    }
 
379
 
 
380
    *tm = mktime(&t);
 
381
    *asn1data = obj.next;
 
382
    return 0;
 
383
}
 
384
 
 
385
static int asn1_get_rsa_pubkey(fmap_t *map, const void **asn1data, unsigned int *size, cli_crt *x509) {
 
386
    struct cli_asn1 obj;
 
387
    unsigned int avail, avail2;
 
388
 
 
389
    if(asn1_expect_objtype(map, *asn1data, size, &obj, 0x30)) /* subjectPublicKeyInfo */
 
390
        return 1;
 
391
    *asn1data = obj.next;
 
392
 
 
393
    avail = obj.size;
 
394
    if(asn1_expect_algo(map, &obj.content, &avail, lenof(OID_rsaEncryption), OID_rsaEncryption)) /* rsaEncryption */
 
395
       return 1;
 
396
 
 
397
    if(asn1_expect_objtype(map, obj.content, &avail, &obj, 0x03)) /* BIT STRING - subjectPublicKey */
 
398
        return 1;
 
399
    if(avail) {
 
400
        cli_dbgmsg("asn1_get_rsa_pubkey: found unexpected extra data in subjectPublicKeyInfo\n");
 
401
        return 1;
 
402
    }
 
403
    /* if(obj.size != 141 && obj.size != 271) /\* encoded len of 1024 and 2048 bit public keys *\/ */
 
404
    /*  return 1; */
 
405
 
 
406
    if(!fmap_need_ptr_once(map, obj.content, 1)) {
 
407
        cli_dbgmsg("asn1_get_rsa_pubkey: cannot read public key content\n");
 
408
        return 1;
 
409
    }
 
410
    if(((uint8_t *)obj.content)[0] != 0) { /* no byte fragments */
 
411
        cli_dbgmsg("asn1_get_rsa_pubkey: unexpected byte frags in public key\n");
 
412
        return 1;
 
413
    }
 
414
 
 
415
    avail = obj.size - 1;
 
416
    obj.content = ((uint8_t *)obj.content) + 1;
 
417
    if(asn1_expect_objtype(map, obj.content, &avail, &obj, 0x30)) /* SEQUENCE */
 
418
        return 1;
 
419
    if(avail) {
 
420
        cli_dbgmsg("asn1_get_rsa_pubkey: found unexpected extra data in public key content\n");
 
421
        return 1;
 
422
    }
 
423
 
 
424
    avail = obj.size;
 
425
    if(asn1_expect_objtype(map, obj.content, &avail, &obj, 0x02)) /* INTEGER - mod */
 
426
        return 1;
 
427
    if(obj.size < 1024/8 || obj.size > 4096/8+1) {
 
428
        cli_dbgmsg("asn1_get_rsa_pubkey: modulus has got an unsupported length (%u)\n",  obj.size * 8);
 
429
        return 1;
 
430
    }
 
431
    avail2 = obj.size;
 
432
    if(!fmap_need_ptr_once(map, obj.content, avail2)) {
 
433
        cli_dbgmsg("asn1_get_rsa_pubkey: cannot read n\n");
 
434
        return 1;
 
435
    }
 
436
    if(mp_read_unsigned_bin(&x509->n, obj.content, avail2)) {
 
437
        cli_dbgmsg("asn1_get_rsa_pubkey: cannot convert n to big number\n");
 
438
        return 1;
 
439
    }
 
440
 
 
441
    if(asn1_expect_objtype(map, obj.next, &avail, &obj, 0x02)) /* INTEGER - exp */
 
442
        return 1;
 
443
    if(avail) {
 
444
        cli_dbgmsg("asn1_get_rsa_pubkey: found unexpected extra data after exp\n");
 
445
        return 1;
 
446
    }
 
447
    if(obj.size < 1 || obj.size > avail2) {
 
448
        cli_dbgmsg("asn1_get_rsa_pubkey: exponent has got an unsupported length (%u)\n",  obj.size * 8);
 
449
        return 1;
 
450
    }
 
451
    if(!fmap_need_ptr_once(map, obj.content, obj.size)) {
 
452
        cli_dbgmsg("asn1_get_rsa_pubkey: cannot read e\n");
 
453
        return 1;
 
454
    }
 
455
    if(mp_read_unsigned_bin(&x509->e, obj.content, obj.size)) {
 
456
        cli_dbgmsg("asn1_get_rsa_pubkey: cannot convert e to big number\n");
 
457
        return 1;
 
458
    }
 
459
    return 0;
 
460
}
 
461
 
 
462
static int asn1_get_x509(fmap_t *map, const void **asn1data, unsigned int *size, crtmgr *master, crtmgr *other) {
 
463
    struct cli_asn1 crt, tbs, obj;
 
464
    unsigned int avail, tbssize, issuersize;
 
465
    cli_crt_hashtype hashtype1, hashtype2;
 
466
    cli_crt x509;
 
467
    const uint8_t *tbsdata;
 
468
    const void *next, *issuer;
 
469
 
 
470
    if(cli_crt_init(&x509))
 
471
        return 1;
 
472
 
 
473
    do {
 
474
        if(asn1_expect_objtype(map, *asn1data, size, &crt, 0x30)) /* SEQUENCE */
 
475
            break;
 
476
        *asn1data = crt.next;
 
477
 
 
478
        tbsdata = crt.content;
 
479
        if(asn1_expect_objtype(map, crt.content, &crt.size, &tbs, 0x30)) /* SEQUENCE - TBSCertificate */
 
480
            break;
 
481
        tbssize = (uint8_t *)tbs.next - tbsdata;
 
482
 
 
483
        if(asn1_expect_objtype(map, tbs.content, &tbs.size, &obj, 0xa0)) /* [0] */
 
484
            break;
 
485
        avail = obj.size;
 
486
        next = obj.next;
 
487
        if(asn1_expect_obj(map, &obj.content, &avail, 0x02, 1, "\x02")) /* version 3 only */
 
488
            break;
 
489
        if(avail) {
 
490
            cli_dbgmsg("asn1_get_x509: found unexpected extra data in version\n");
 
491
            break;
 
492
        }
 
493
 
 
494
        if(asn1_expect_objtype(map, next, &tbs.size, &obj, 0x02)) /* serialNumber */
 
495
            break;
 
496
        if(map_sha1(map, obj.content, obj.size, x509.serial))
 
497
            break;
 
498
 
 
499
        if(asn1_expect_rsa(map, &obj.next, &tbs.size, &hashtype1)) /* algo = sha1WithRSAEncryption | md5WithRSAEncryption */
 
500
            break;
 
501
 
 
502
        if(asn1_expect_objtype(map, obj.next, &tbs.size, &obj, 0x30)) /* issuer */
 
503
            break;
 
504
        issuer = obj.content;
 
505
        issuersize = obj.size;
 
506
 
 
507
        if(asn1_expect_objtype(map, obj.next, &tbs.size, &obj, 0x30)) /* validity */
 
508
            break;
 
509
        avail = obj.size;
 
510
        next = obj.content;
 
511
 
 
512
        if(asn1_get_time(map, &next, &avail, &x509.not_before)) /* notBefore */
 
513
            break;
 
514
        if(asn1_get_time(map, &next, &avail, &x509.not_after)) /* notAfter */
 
515
            break;
 
516
        if(x509.not_before >= x509.not_after) {
 
517
            cli_dbgmsg("asn1_get_x509: bad validity\n");
 
518
            break;
 
519
        }
 
520
        if(avail) {
 
521
            cli_dbgmsg("asn1_get_x509: found unexpected extra data in validity\n");
 
522
            break;
 
523
        }
 
524
 
 
525
        if(asn1_expect_objtype(map, obj.next, &tbs.size, &obj, 0x30)) /* subject */
 
526
            break;
 
527
        if(map_sha1(map, obj.content, obj.size, x509.subject))
 
528
            break;
 
529
        if(asn1_get_rsa_pubkey(map, &obj.next, &tbs.size, &x509))
 
530
            break;
 
531
 
 
532
        avail = 0;
 
533
        while(tbs.size) {
 
534
            if(asn1_get_obj(map, obj.next, &tbs.size, &obj)) {
 
535
                tbs.size = 1;
 
536
                break;
 
537
            }
 
538
            if(obj.type <= 0xa0 + avail || obj.type > 0xa3) {
 
539
                cli_dbgmsg("asn1_get_x509: found type %02x in extensions, expecting a1, a2 or a3\n", obj.type);
 
540
                tbs.size = 1;
 
541
                break;
 
542
            }
 
543
            avail = obj.type - 0xa0;
 
544
            if(obj.type == 0xa3) {
 
545
                struct cli_asn1 exts;
 
546
                int have_ext_key = 0;
 
547
                if(asn1_expect_objtype(map, obj.content, &obj.size, &exts, 0x30)) {
 
548
                    tbs.size = 1;
 
549
                    break;
 
550
                }
 
551
                if(obj.size) {
 
552
                    cli_dbgmsg("asn1_get_x509: found unexpected extra data in extensions\n");
 
553
                    break;
 
554
                }
 
555
                while(exts.size) {
 
556
                    struct cli_asn1 ext, id, value;
 
557
                    if(asn1_expect_objtype(map, exts.content, &exts.size, &ext, 0x30)) {
 
558
                        exts.size = 1;
 
559
                        break;
 
560
                    }
 
561
                    exts.content = ext.next;
 
562
                    if(asn1_expect_objtype(map, ext.content, &ext.size, &id, 0x06)) {
 
563
                        exts.size = 1;
 
564
                        break;
 
565
                    }
 
566
                    if(asn1_get_obj(map, id.next, &ext.size, &value)) {
 
567
                        exts.size = 1;
 
568
                        break;
 
569
                    }
 
570
                    if(value.type == 0x01) {
 
571
                        /* critical flag */
 
572
                        if(value.size != 1) {
 
573
                            cli_dbgmsg("asn1_get_x509: found boolean with wrong length\n");
 
574
                            exts.size = 1;
 
575
                            break;
 
576
                        }
 
577
                        if(asn1_get_obj(map, value.next, &ext.size, &value)) {
 
578
                            exts.size = 1;
 
579
                            break;
 
580
                        }
 
581
                    }
 
582
                    if(value.type != 0x04) {
 
583
                        cli_dbgmsg("asn1_get_x509: bad extension value type %u\n", value.type);
 
584
                        exts.size = 1;
 
585
                        break;
 
586
                    }
 
587
                    if(ext.size) {
 
588
                        cli_dbgmsg("asn1_get_x509: extra data in extension\n");
 
589
                        exts.size = 1;
 
590
                        break;
 
591
                    }
 
592
                    if(id.size != 3)
 
593
                        continue;
 
594
 
 
595
                    if(!fmap_need_ptr_once(map, id.content, 3)) {
 
596
                        exts.size = 1;
 
597
                        break;
 
598
                    }
 
599
                    if(!memcmp("\x55\x1d\x0f", id.content, 3)) {
 
600
                        /* KeyUsage 2.5.29.15 */
 
601
                        const uint8_t *keyusage = value.content;
 
602
                        uint8_t usage;
 
603
                        if(value.size < 4 || value.size > 5) {
 
604
                            cli_dbgmsg("asn1_get_x509: bad KeyUsage\n");
 
605
                            exts.size = 1;
 
606
                            break;
 
607
                        }
 
608
                        if(!fmap_need_ptr_once(map, value.content, value.size)) {
 
609
                            exts.size = 1;
 
610
                            break;
 
611
                        }
 
612
                        if(keyusage[0] != 0x03 || keyusage[1] != value.size - 2 || keyusage[2] > 7) {
 
613
                            cli_dbgmsg("asn1_get_x509: bad KeyUsage\n");
 
614
                            exts.size = 1;
 
615
                            break;
 
616
                        }
 
617
                        usage = keyusage[3];
 
618
                        if(value.size == 4)
 
619
                            usage &= ~((1 << keyusage[2])-1);
 
620
                        x509.certSign = ((usage & 4) != 0);
 
621
                        continue;
 
622
                    }
 
623
                    if(!memcmp("\x55\x1d\x25", id.content, 3)) {
 
624
                        /* ExtKeyUsage 2.5.29.37 */
 
625
                        struct cli_asn1 keypurp;
 
626
                        have_ext_key = 1;
 
627
                        if(asn1_expect_objtype(map, value.content, &value.size, &keypurp, 0x30)) {
 
628
                            exts.size = 1;
 
629
                            break;
 
630
                        }
 
631
                        if(value.size) {
 
632
                            cli_dbgmsg("asn1_get_x509: extra data in ExtKeyUsage\n");
 
633
                            exts.size = 1;
 
634
                            break;
 
635
                        }
 
636
                        ext.next = keypurp.content;
 
637
                        while(keypurp.size) {
 
638
                            if(asn1_expect_objtype(map, ext.next, &keypurp.size, &ext, 0x06)) {
 
639
                                exts.size = 1;
 
640
                                break;
 
641
                            }
 
642
                            if(ext.size != 8)
 
643
                                continue;
 
644
                            if(!fmap_need_ptr_once(map, ext.content, 8)) {
 
645
                                exts.size = 1;
 
646
                                break;
 
647
                            }
 
648
                            if(!memcmp("\x2b\x06\x01\x05\x05\x07\x03\x03", ext.content, 8)) /* id_kp_codeSigning */
 
649
                                x509.codeSign = 1;
 
650
                            else if(!memcmp("\x2b\x06\x01\x05\x05\x07\x03\x08", ext.content, 8)) /* id_kp_timeStamping */
 
651
                                x509.timeSign = 1;
 
652
                        }
 
653
                        continue;
 
654
                    }
 
655
                    if(!memcmp("\x55\x1d\x13", id.content, 3)) {
 
656
                        /* Basic Constraints 2.5.29.19 */
 
657
                        struct cli_asn1 constr;
 
658
                        if(asn1_expect_objtype(map, value.content, &value.size, &constr, 0x30)) {
 
659
                            exts.size = 1;
 
660
                            break;
 
661
                        }
 
662
                        if(!constr.size)
 
663
                            x509.certSign = 0;
 
664
                        else {
 
665
                            if(asn1_expect_objtype(map, constr.content, &constr.size, &ext, 0x01)) {
 
666
                                exts.size = 1;
 
667
                                break;
 
668
                            }
 
669
                            if(ext.size != 1) {
 
670
                                cli_dbgmsg("asn1_get_x509: wrong bool size in basic constraint %u\n", ext.size);
 
671
                                exts.size = 1;
 
672
                                break;
 
673
                            }
 
674
                            if(!fmap_need_ptr_once(map, ext.content, 1)) {
 
675
                                exts.size = 1;
 
676
                                break;
 
677
                            }
 
678
                            x509.certSign = (((uint8_t *)(ext.content))[0] != 0);
 
679
                        }
 
680
                    }
 
681
                }
 
682
                if(exts.size) {
 
683
                    tbs.size = 1;
 
684
                    break;
 
685
                }
 
686
                if(!have_ext_key)
 
687
                    x509.codeSign = x509.timeSign = 1;
 
688
            }
 
689
        }
 
690
        if(tbs.size)
 
691
            break;
 
692
 
 
693
 
 
694
        if(crtmgr_lookup(master, &x509) || crtmgr_lookup(other, &x509)) {
 
695
            cli_dbgmsg("asn1_get_x509: certificate already exists\n");
 
696
            cli_crt_clear(&x509);
 
697
            return 0;
 
698
        }
 
699
 
 
700
        if(map_sha1(map, issuer, issuersize, x509.issuer))
 
701
            break;
 
702
 
 
703
        if(asn1_expect_rsa(map, &tbs.next, &crt.size, &hashtype2)) /* signature algo = sha1WithRSAEncryption | md5WithRSAEncryption */
 
704
            break;
 
705
 
 
706
        if(hashtype1 != hashtype2) {
 
707
            cli_dbgmsg("asn1_get_x509: found conflicting rsa hash types\n");
 
708
            break;
 
709
        }
 
710
        x509.hashtype = hashtype1;
 
711
 
 
712
        if(asn1_expect_objtype(map, tbs.next, &crt.size, &obj, 0x03)) /* signature */
 
713
            break;
 
714
        if(obj.size > 513) {
 
715
            cli_dbgmsg("asn1_get_x509: signature too long\n");
 
716
            break;
 
717
        }
 
718
        if(!fmap_need_ptr_once(map, obj.content, obj.size)) {
 
719
            cli_dbgmsg("asn1_get_x509: cannot read signature\n");
 
720
            break;
 
721
        }
 
722
        if(mp_read_unsigned_bin(&x509.sig, obj.content, obj.size)) {
 
723
            cli_dbgmsg("asn1_get_x509: cannot convert signature to big number\n");
 
724
            break;
 
725
        }
 
726
        if(crt.size) {
 
727
            cli_dbgmsg("asn1_get_x509: found unexpected extra data in signature\n");
 
728
            break;
 
729
        }
 
730
 
 
731
        if((x509.hashtype == CLI_SHA1RSA && map_sha1(map, tbsdata, tbssize, x509.tbshash)) || (x509.hashtype == CLI_MD5RSA && (map_md5(map, tbsdata, tbssize, x509.tbshash))))
 
732
            break;
 
733
 
 
734
        if(crtmgr_add(other, &x509))
 
735
            break;
 
736
        cli_crt_clear(&x509);
 
737
        return 0;
 
738
    } while(0);
 
739
    cli_crt_clear(&x509);
 
740
    return 1;
 
741
}
 
742
 
 
743
static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmgr *cmgr, int embedded, const void **hashes, unsigned int *hashes_size, struct cl_engine *engine) {
 
744
    struct cli_asn1 asn1, deep, deeper;
 
745
    uint8_t sha1[SHA1_HASH_SIZE], issuer[SHA1_HASH_SIZE], md[SHA1_HASH_SIZE], serial[SHA1_HASH_SIZE];
 
746
    const uint8_t *message, *attrs;
 
747
    unsigned int dsize, message_size, attrs_size;
 
748
    cli_crt_hashtype hashtype;
 
749
    SHA1Context ctx;
 
750
    cli_crt *x509;
 
751
    int result;
 
752
    int isBlacklisted = 0;
 
753
 
 
754
    cli_dbgmsg("in asn1_parse_mscat\n");
 
755
 
 
756
    do {
 
757
        if(!(message = fmap_need_off_once(map, offset, 1))) {
 
758
            cli_dbgmsg("asn1_parse_mscat: failed to read pkcs#7 entry\n");
 
759
            break;
 
760
        }
 
761
 
 
762
        if(asn1_expect_objtype(map, message, &size, &asn1, 0x30)) /* SEQUENCE */
 
763
            break;
 
764
        /* if(size) { */
 
765
        /*     cli_dbgmsg("asn1_parse_mscat: found extra data after pkcs#7 %u\n", size); */
 
766
        /*     break; */
 
767
        /* } */
 
768
        size = asn1.size;
 
769
        if(asn1_expect_obj(map, &asn1.content, &size, 0x06, lenof(OID_signedData), OID_signedData)) /* OBJECT 1.2.840.113549.1.7.2 - contentType = signedData */
 
770
            break;
 
771
        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0xa0)) /* [0] - content */
 
772
            break;
 
773
        if(size) {
 
774
            cli_dbgmsg("asn1_parse_mscat: found extra data in pkcs#7\n");
 
775
            break;
 
776
        }
 
777
        size = asn1.size;
 
778
        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) /* SEQUENCE */
 
779
            break;
 
780
        if(size) {
 
781
            cli_dbgmsg("asn1_parse_mscat: found extra data in signedData\n");
 
782
            break;
 
783
        }
 
784
        size = asn1.size;
 
785
        if(asn1_expect_obj(map, &asn1.content, &size, 0x02, 1, "\x01")) /* INTEGER - VERSION 1 */
 
786
            break;
 
787
 
 
788
        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x31)) /* SET OF DigestAlgorithmIdentifier */
 
789
            break;
 
790
 
 
791
        if(asn1_expect_algo(map, &asn1.content, &asn1.size, lenof(OID_sha1), OID_sha1)) /* DigestAlgorithmIdentifier[0] == sha1 */
 
792
            break;
 
793
        if(asn1.size) {
 
794
            cli_dbgmsg("asn1_parse_mscat: only one digestAlgorithmIdentifier is allowed\n");
 
795
            break;
 
796
        }
 
797
 
 
798
        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x30)) /* SEQUENCE - contentInfo */
 
799
            break;
 
800
        /* Here there is either a PKCS #7 ContentType Object Identifier for Certificate Trust List (szOID_CTL)
 
801
         * or a single SPC_INDIRECT_DATA_OBJID */
 
802
        if(
 
803
           (!embedded && asn1_expect_obj(map, &asn1.content, &asn1.size, 0x06, lenof(OID_szOID_CTL), OID_szOID_CTL)) ||
 
804
           (embedded && asn1_expect_obj(map, &asn1.content, &asn1.size, 0x06, lenof(OID_SPC_INDIRECT_DATA_OBJID), OID_SPC_INDIRECT_DATA_OBJID))
 
805
           )
 
806
            break;
 
807
 
 
808
        if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0xa0))
 
809
            break;
 
810
        if(asn1.size) {
 
811
            cli_dbgmsg("asn1_parse_mscat: found extra data in contentInfo\n");
 
812
            break;
 
813
        }
 
814
        dsize = deep.size;
 
815
        if(asn1_expect_objtype(map, deep.content, &dsize, &deep, 0x30))
 
816
            break;
 
817
        if(dsize) {
 
818
            cli_dbgmsg("asn1_parse_mscat: found extra data in content\n");
 
819
            break;
 
820
        }
 
821
        *hashes = deep.content;
 
822
        *hashes_size = deep.size;
 
823
 
 
824
        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) /* certificates */
 
825
            break;
 
826
 
 
827
        dsize = asn1.size;
 
828
        if(dsize) {
 
829
            crtmgr newcerts;
 
830
            crtmgr_init(&newcerts);
 
831
            while(dsize) {
 
832
                if(asn1_get_x509(map, &asn1.content, &dsize, cmgr, &newcerts)) {
 
833
                    dsize = 1;
 
834
                    break;
 
835
                }
 
836
            }
 
837
            if(dsize)
 
838
                break;
 
839
            if(newcerts.crts) {
 
840
                x509 = newcerts.crts;
 
841
                cli_dbgmsg("asn1_parse_mscat: %u new certificates collected\n", newcerts.items);
 
842
                while(x509) {
 
843
                    cli_crt *parent = crtmgr_verify_crt(cmgr, x509);
 
844
 
 
845
            /* Dump the cert if requested before anything happens to it */
 
846
            if (engine->dconf->pe & PE_CONF_DUMPCERT) {
 
847
                char issuer[SHA1_HASH_SIZE*2+1], subject[SHA1_HASH_SIZE*2+1], serial[SHA1_HASH_SIZE*2+1];
 
848
                char mod[1024], exp[1024];
 
849
                int j=1024;
 
850
 
 
851
                fp_toradix_n(&x509->n, mod, 16, j);
 
852
                fp_toradix_n(&x509->e, exp, 16, j);
 
853
                for (j=0; j < SHA1_HASH_SIZE; j++) {
 
854
                    sprintf(&issuer[j*2], "%02x", x509->issuer[j]);
 
855
                    sprintf(&subject[j*2], "%02x", x509->subject[j]);
 
856
                    sprintf(&serial[j*2], "%02x", x509->serial[j]);
 
857
                }
 
858
 
 
859
                cli_dbgmsg_internal("cert subject:%s serial:%s pubkey:%s i:%s %lu->%lu %s %s %s\n", subject, serial, mod, issuer, (unsigned long)x509->not_before, (unsigned long)x509->not_after, x509->certSign ? "cert" : "", x509->codeSign ? "code" : "", x509->timeSign ? "time" : "");
 
860
            }
 
861
 
 
862
                    if(parent) {
 
863
                if (parent->isBlacklisted) {
 
864
                    isBlacklisted = 1;
 
865
                    cli_dbgmsg("asn1_parse_mscat: Authenticode certificate %s is revoked. Flagging sample as virus.\n", (parent->name ? parent->name : "(no name)"));
 
866
                }
 
867
 
 
868
                        x509->codeSign &= parent->codeSign;
 
869
                        x509->timeSign &= parent->timeSign;
 
870
            if(crtmgr_add(cmgr, x509))
 
871
                break;
 
872
            crtmgr_del(&newcerts, x509);
 
873
                        x509 = newcerts.crts;
 
874
                        continue;
 
875
                    }
 
876
                    x509 = x509->next;
 
877
                }
 
878
                if(x509)
 
879
                    break;
 
880
                if(newcerts.items)
 
881
                    cli_dbgmsg("asn1_parse_mscat: %u certificates did not verify\n", newcerts.items);
 
882
                crtmgr_free(&newcerts);
 
883
            }
 
884
        }
 
885
 
 
886
        if(asn1_get_obj(map, asn1.next, &size, &asn1))
 
887
            break;
 
888
        if(asn1.type == 0xa1 && asn1_get_obj(map, asn1.next, &size, &asn1)) /* crls - unused shouldn't be present */
 
889
            break;
 
890
        if(asn1.type != 0x31) { /* signerInfos */
 
891
            cli_dbgmsg("asn1_parse_mscat: unexpected type %02x for signerInfos\n", asn1.type);
 
892
            break;
 
893
        }
 
894
        if(size) {
 
895
            cli_dbgmsg("asn1_parse_mscat: unexpected extra data after signerInfos\n");
 
896
            break;
 
897
        }
 
898
        size = asn1.size;
 
899
        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30))
 
900
            break;
 
901
        if(size) {
 
902
            cli_dbgmsg("asn1_parse_mscat: only one signerInfo shall be present\n");
 
903
            break;
 
904
        }
 
905
        size = asn1.size;
 
906
        if(asn1_expect_obj(map, &asn1.content, &size, 0x02, 1, "\x01")) /* Version = 1 */
 
907
            break;
 
908
        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) /* issuerAndSerialNumber */
 
909
            break;
 
910
        dsize = asn1.size;
 
911
        if(asn1_expect_objtype(map, asn1.content, &dsize, &deep, 0x30)) /* issuer */
 
912
            break;
 
913
        if(map_sha1(map, deep.content, deep.size, issuer))
 
914
            break;
 
915
 
 
916
        if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x02)) /* serial */
 
917
            break;
 
918
        if(map_sha1(map, deep.content, deep.size, serial))
 
919
            break;
 
920
        if(dsize) {
 
921
            cli_dbgmsg("asn1_parse_mscat: extra data inside issuerAndSerialNumber\n");
 
922
            break;
 
923
        }
 
924
        if(asn1_expect_algo(map, &asn1.next, &size, lenof(OID_sha1), OID_sha1)) /* digestAlgorithm == sha1 */
 
925
            break;
 
926
 
 
927
        attrs = asn1.next;
 
928
        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) /* authenticatedAttributes */
 
929
            break;
 
930
        attrs_size = (uint8_t *)(asn1.next) - attrs;
 
931
        if(attrs_size < 2) {
 
932
            cli_dbgmsg("asn1_parse_mscat: authenticatedAttributes size is too small\n");
 
933
            break;
 
934
        }
 
935
 
 
936
        dsize = asn1.size;
 
937
        deep.next = asn1.content;
 
938
        result = 0;
 
939
        while(dsize) {
 
940
            struct cli_asn1 cobj;
 
941
            int content;
 
942
            if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x30)) { /* attribute */
 
943
                dsize = 1;
 
944
                break;
 
945
            }
 
946
            if(asn1_expect_objtype(map, deep.content, &deep.size, &deeper, 0x06)) { /* attribute type */
 
947
                dsize = 1;
 
948
                break;
 
949
            }
 
950
            if(deeper.size != lenof(OID_contentType))
 
951
                continue;
 
952
            if(!fmap_need_ptr_once(map, deeper.content, lenof(OID_contentType))) {
 
953
                cli_dbgmsg("asn1_parse_mscat: failed to read authenticated attribute\n");
 
954
                dsize = 1;
 
955
                break;
 
956
            }
 
957
            if(!memcmp(deeper.content, OID_contentType, lenof(OID_contentType)))
 
958
                content = 0; /* contentType */
 
959
            else if(!memcmp(deeper.content, OID_messageDigest, lenof(OID_messageDigest)))
 
960
                content = 1; /* messageDigest */
 
961
            else
 
962
                continue;
 
963
            if(asn1_expect_objtype(map, deeper.next, &deep.size, &deeper, 0x31)) { /* set - contents */
 
964
                dsize = 1;
 
965
                break;
 
966
            }
 
967
            if(deep.size) {
 
968
                cli_dbgmsg("asn1_parse_mscat: extra data in authenticated attributes\n");
 
969
                dsize = 1;
 
970
                break;
 
971
            }
 
972
 
 
973
            if(result & (1<<content)) {
 
974
                cli_dbgmsg("asn1_parse_mscat: contentType or messageDigest appear twice\n");
 
975
                dsize = 1;
 
976
                break;
 
977
            }
 
978
 
 
979
            if(content == 0) { /* contentType */
 
980
                if(
 
981
                   (!embedded && asn1_expect_obj(map, &deeper.content, &deeper.size, 0x06, lenof(OID_szOID_CTL), OID_szOID_CTL)) || /* cat file */
 
982
                   (embedded && asn1_expect_obj(map, &deeper.content, &deeper.size, 0x06, lenof(OID_SPC_INDIRECT_DATA_OBJID), OID_SPC_INDIRECT_DATA_OBJID)) /* embedded cat */
 
983
                  ) {
 
984
                    dsize = 1;
 
985
                    break;
 
986
                }
 
987
                result |= 1;
 
988
            } else { /* messageDigest */
 
989
                if(asn1_expect_objtype(map, deeper.content, &deeper.size, &cobj, 0x04)) {
 
990
                    dsize = 1;
 
991
                    break;
 
992
                }
 
993
                if(cobj.size != SHA1_HASH_SIZE) {
 
994
                    cli_dbgmsg("asn1_parse_mscat: messageDigest attribute has got the wrong size (%u)\n", cobj.size);
 
995
                    dsize = 1;
 
996
                    break;
 
997
                }
 
998
                if(!fmap_need_ptr_once(map, cobj.content, SHA1_HASH_SIZE)) {
 
999
                    cli_dbgmsg("asn1_parse_mscat: failed to read authenticated attribute\n");
 
1000
                    dsize = 1;
 
1001
                    break;
 
1002
                }
 
1003
                memcpy(md, cobj.content, SHA1_HASH_SIZE);
 
1004
                result |= 2;
 
1005
            }
 
1006
            if(deeper.size) {
 
1007
                cli_dbgmsg("asn1_parse_mscat: extra data in authenticated attribute\n");
 
1008
                dsize = 1;
 
1009
                break;
 
1010
            }
 
1011
        }
 
1012
        if(dsize)
 
1013
            break;
 
1014
        if(result != 3) {
 
1015
            cli_dbgmsg("asn1_parse_mscat: contentType or messageDigest are missing\n");
 
1016
            break;
 
1017
        }
 
1018
 
 
1019
        if(asn1_expect_algo(map, &asn1.next, &size, lenof(OID_rsaEncryption), OID_rsaEncryption)) /* digestEncryptionAlgorithm == sha1 */
 
1020
            break;
 
1021
 
 
1022
        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x04)) /* encryptedDigest */
 
1023
            break;
 
1024
        if(asn1.size > 513) {
 
1025
            cli_dbgmsg("asn1_parse_mscat: encryptedDigest too long\n");
 
1026
            break;
 
1027
        }
 
1028
        if(map_sha1(map, *hashes, *hashes_size, sha1))
 
1029
            break;
 
1030
        if(memcmp(sha1, md, sizeof(sha1))) {
 
1031
            cli_dbgmsg("asn1_parse_mscat: messageDigest mismatch\n");
 
1032
            break;
 
1033
        }
 
1034
 
 
1035
        if(!fmap_need_ptr_once(map, attrs, attrs_size)) {
 
1036
            cli_dbgmsg("asn1_parse_mscat: failed to read authenticatedAttributes\n");
 
1037
            break;
 
1038
        }
 
1039
 
 
1040
        SHA1Init(&ctx);
 
1041
        SHA1Update(&ctx, "\x31", 1);
 
1042
        SHA1Update(&ctx, attrs + 1, attrs_size - 1);
 
1043
        SHA1Final(&ctx, sha1);
 
1044
 
 
1045
        if(!fmap_need_ptr_once(map, asn1.content, asn1.size)) {
 
1046
            cli_dbgmsg("asn1_parse_mscat: failed to read encryptedDigest\n");
 
1047
            break;
 
1048
        }
 
1049
        if(!(x509 = crtmgr_verify_pkcs7(cmgr, issuer, serial, asn1.content, asn1.size, CLI_SHA1RSA, sha1, VRFY_CODE))) {
 
1050
            cli_dbgmsg("asn1_parse_mscat: pkcs7 signature verification failed\n");
 
1051
            break;
 
1052
        }
 
1053
        message = asn1.content;
 
1054
        message_size = asn1.size;
 
1055
 
 
1056
        if(!size) {
 
1057
            cli_dbgmsg("asn1_parse_mscat: countersignature is missing\n");
 
1058
            break;
 
1059
        }
 
1060
 
 
1061
        if(size && asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa1)) /* unauthenticatedAttributes */
 
1062
            break;
 
1063
 
 
1064
        if(size) {
 
1065
            cli_dbgmsg("asn1_parse_mscat: extra data inside signerInfo\n");
 
1066
            break;
 
1067
        }
 
1068
 
 
1069
        size = asn1.size;
 
1070
        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30))
 
1071
            break;
 
1072
        if(size) {
 
1073
            cli_dbgmsg("asn1_parse_mscat: extra data inside unauthenticatedAttributes\n");
 
1074
            break;
 
1075
        }
 
1076
 
 
1077
        size = asn1.size;
 
1078
        /* 1.2.840.113549.1.9.6 - counterSignature */
 
1079
        if(asn1_expect_obj(map, &asn1.content, &size, 0x06, lenof(OID_countersignature), OID_countersignature))
 
1080
            break;
 
1081
        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x31))
 
1082
            break;
 
1083
        if(size) {
 
1084
            cli_dbgmsg("asn1_parse_mscat: extra data inside counterSignature\n");
 
1085
            break;
 
1086
        }
 
1087
 
 
1088
        size = asn1.size;
 
1089
        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30))
 
1090
            break;
 
1091
        if(size) {
 
1092
            cli_dbgmsg("asn1_parse_mscat: extra data inside unauthenticatedAttributes\n");
 
1093
            break;
 
1094
        }
 
1095
 
 
1096
        size = asn1.size;
 
1097
        if(asn1_expect_obj(map, &asn1.content, &size, 0x02, 1, "\x01")) /* Version = 1*/
 
1098
            break;
 
1099
 
 
1100
        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, 0x30)) /* issuerAndSerialNumber */
 
1101
            break;
 
1102
 
 
1103
        if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0x30)) /* issuer */
 
1104
            break;
 
1105
        if(map_sha1(map, deep.content, deep.size, issuer))
 
1106
            break;
 
1107
 
 
1108
        if(asn1_expect_objtype(map, deep.next, &asn1.size, &deep, 0x02)) /* serial */
 
1109
            break;
 
1110
        if(map_sha1(map, deep.content, deep.size, serial))
 
1111
            break;
 
1112
 
 
1113
        if(asn1.size) {
 
1114
            cli_dbgmsg("asn1_parse_mscat: extra data inside countersignature issuer\n");
 
1115
            break;
 
1116
        }
 
1117
 
 
1118
        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x30)) /* digestAlgorithm */
 
1119
            break;
 
1120
        if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0x06))
 
1121
            break;
 
1122
        if(deep.size != lenof(OID_sha1) && deep.size != lenof(OID_md5)) {
 
1123
            cli_dbgmsg("asn1_parse_mscat: wrong digestAlgorithm size\n");
 
1124
            break;
 
1125
        }
 
1126
        if(!fmap_need_ptr_once(map, deep.content, deep.size)) {
 
1127
            cli_dbgmsg("asn1_parse_mscat: failed to read digestAlgorithm OID\n");
 
1128
            break;
 
1129
        }
 
1130
        if(deep.size == lenof(OID_sha1) && !memcmp(deep.content, OID_sha1, lenof(OID_sha1))) {
 
1131
            hashtype = CLI_SHA1RSA;
 
1132
            if(map_sha1(map, message, message_size, md))
 
1133
                break;
 
1134
        } else if(deep.size == lenof(OID_md5) && !memcmp(deep.content, OID_md5, lenof(OID_md5))) {
 
1135
            hashtype = CLI_MD5RSA;
 
1136
            if(map_md5(map, message, message_size, md))
 
1137
                break;
 
1138
        } else {
 
1139
            cli_dbgmsg("asn1_parse_mscat: unknown digest oid in countersignature\n");
 
1140
            break;
 
1141
        }
 
1142
        if(asn1.size && asn1_expect_obj(map, &deep.next, &asn1.size, 0x05, 0, NULL))
 
1143
            break;
 
1144
        if(asn1.size) {
 
1145
            cli_dbgmsg("asn1_parse_mscat: extra data in countersignature oid\n");
 
1146
            break;
 
1147
        }
 
1148
 
 
1149
        attrs = asn1.next;
 
1150
        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) /* authenticatedAttributes */
 
1151
            break;
 
1152
        attrs_size = (uint8_t *)(asn1.next) - attrs;
 
1153
        if(attrs_size < 2) {
 
1154
            cli_dbgmsg("asn1_parse_mscat: countersignature authenticatedAttributes are too small\n");
 
1155
            break;
 
1156
        }
 
1157
        result = 0;
 
1158
        dsize = asn1.size;
 
1159
        deep.next = asn1.content;
 
1160
        while(dsize) {
 
1161
            int content;
 
1162
            if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x30)) { /* attribute */
 
1163
                dsize = 1;
 
1164
                break;
 
1165
            }
 
1166
            if(asn1_expect_objtype(map, deep.content, &deep.size, &deeper, 0x06)) { /* attribute type */
 
1167
                dsize = 1;
 
1168
                break;
 
1169
            }
 
1170
            if(deeper.size != lenof(OID_contentType)) /* lenof(contentType) = lenof(messageDigest) = lenof(signingTime) = 9 */
 
1171
                continue;
 
1172
 
 
1173
            if(!fmap_need_ptr_once(map, deeper.content, lenof(OID_contentType))) {
 
1174
                dsize = 1;
 
1175
                break;
 
1176
            }
 
1177
            if(!memcmp(deeper.content, OID_contentType, lenof(OID_contentType)))
 
1178
                content = 0; /* contentType */
 
1179
            else if(!memcmp(deeper.content, OID_messageDigest, lenof(OID_messageDigest)))
 
1180
                content = 1; /* messageDigest */
 
1181
            else if(!memcmp(deeper.content, OID_signingTime, lenof(OID_signingTime)))
 
1182
                content = 2; /* signingTime */
 
1183
            else
 
1184
                continue;
 
1185
            if(result & (1<<content)) {
 
1186
                cli_dbgmsg("asn1_parse_mscat: duplicate field in countersignature\n");
 
1187
                dsize = 1;
 
1188
                break;
 
1189
            }
 
1190
            result |= (1<<content);
 
1191
            if(asn1_expect_objtype(map, deeper.next, &deep.size, &deeper, 0x31)) { /* attribute type */
 
1192
                dsize = 1;
 
1193
                break;
 
1194
            }
 
1195
            if(deep.size) {
 
1196
                cli_dbgmsg("asn1_parse_mscat: extra data in countersignature value\n");
 
1197
                dsize = 1;
 
1198
                break;
 
1199
            }
 
1200
            deep.size = deeper.size;
 
1201
            switch(content) {
 
1202
            case 0:  /* contentType = pkcs7-data */
 
1203
                if(asn1_expect_obj(map, &deeper.content, &deep.size, 0x06, lenof(OID_pkcs7_data), OID_pkcs7_data))
 
1204
                    deep.size = 1;
 
1205
                else if(deep.size)
 
1206
                    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature content-type\n");
 
1207
                break;
 
1208
            case 1:  /* messageDigest */
 
1209
                if(asn1_expect_obj(map, &deeper.content, &deep.size, 0x04, (hashtype == CLI_SHA1RSA) ? SHA1_HASH_SIZE : 16, md)) {
 
1210
                    deep.size = 1;
 
1211
                    cli_dbgmsg("asn1_parse_mscat: countersignature hash mismatch\n");
 
1212
                } else if(deep.size)
 
1213
                    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature message-digest\n");
 
1214
                break;
 
1215
            case 2:  /* signingTime */
 
1216
                {
 
1217
                    time_t sigdate; /* FIXME shall i use it?! */
 
1218
                    if(asn1_get_time(map, &deeper.content, &deep.size, &sigdate))
 
1219
                        deep.size = 1;
 
1220
                    else if(deep.size)
 
1221
                        cli_dbgmsg("asn1_parse_mscat: extra data in countersignature signing-time\n");
 
1222
                    else if(sigdate < x509->not_before || sigdate > x509->not_after) {
 
1223
                        cli_dbgmsg("asn1_parse_mscat: countersignature timestamp outside cert validity\n");
 
1224
                        deep.size = 1;
 
1225
                    }
 
1226
                    break;
 
1227
                }
 
1228
            }
 
1229
            if(deep.size) {
 
1230
                dsize = 1;
 
1231
                break;
 
1232
            }
 
1233
        }
 
1234
        if(dsize)
 
1235
            break;
 
1236
        if(result != 7) {
 
1237
            cli_dbgmsg("asn1_parse_mscat: some important attributes are missing in countersignature\n");
 
1238
            break;
 
1239
        }
 
1240
 
 
1241
        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x30)) /* digestEncryptionAlgorithm == sha1 */
 
1242
            break;
 
1243
        if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, 0x06)) /* digestEncryptionAlgorithm == sha1 */
 
1244
            break;
 
1245
        if(deep.size != lenof(OID_rsaEncryption)) { /* lenof(OID_rsaEncryption) = lenof(OID_sha1WithRSAEncryption) = 9 */
 
1246
            cli_dbgmsg("asn1_parse_mscat: wrong digestEncryptionAlgorithm size in countersignature\n");
 
1247
            break;
 
1248
        }
 
1249
        if(!fmap_need_ptr_once(map, deep.content, lenof(OID_rsaEncryption))) {
 
1250
            cli_dbgmsg("asn1_parse_mscat: cannot read digestEncryptionAlgorithm in countersignature\n");
 
1251
            break;
 
1252
        }
 
1253
        /* rsaEncryption or sha1withRSAEncryption */
 
1254
        if(memcmp(deep.content, OID_rsaEncryption, lenof(OID_rsaEncryption)) && memcmp(deep.content, OID_sha1WithRSAEncryption, lenof(OID_sha1WithRSAEncryption))) {
 
1255
            cli_dbgmsg("asn1_parse_mscat: digestEncryptionAlgorithm in countersignature is not sha1\n");
 
1256
            break;
 
1257
        }
 
1258
        if(asn1.size && asn1_expect_obj(map, &deep.next, &asn1.size, 0x05, 0, NULL))
 
1259
            break;
 
1260
        if(asn1.size) {
 
1261
            cli_dbgmsg("asn1_parse_mscat: extra data in digestEncryptionAlgorithm in countersignature\n");
 
1262
            break;
 
1263
        }
 
1264
 
 
1265
        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x04)) /* encryptedDigest */
 
1266
            break;
 
1267
        if(asn1.size > 513) {
 
1268
            cli_dbgmsg("asn1_parse_mscat: countersignature encryptedDigest too long\n");
 
1269
            break;
 
1270
        }
 
1271
        if(size) {
 
1272
            cli_dbgmsg("asn1_parse_mscat: extra data inside countersignature\n");
 
1273
            break;
 
1274
        }
 
1275
        if(!fmap_need_ptr_once(map, attrs, attrs_size)) {
 
1276
            cli_dbgmsg("asn1_parse_mscat: failed to read authenticatedAttributes\n");
 
1277
            break;
 
1278
        }
 
1279
 
 
1280
        if(hashtype == CLI_SHA1RSA) {
 
1281
            SHA1Init(&ctx);
 
1282
            SHA1Update(&ctx, "\x31", 1);
 
1283
            SHA1Update(&ctx, attrs + 1, attrs_size - 1);
 
1284
            SHA1Final(&ctx, sha1);
 
1285
        } else {
 
1286
            cli_md5_ctx ctx;
 
1287
            cli_md5_init(&ctx);
 
1288
            cli_md5_update(&ctx, "\x31", 1);
 
1289
            cli_md5_update(&ctx, attrs + 1, attrs_size - 1);
 
1290
            cli_md5_final(sha1, &ctx);
 
1291
        }
 
1292
 
 
1293
        if(!fmap_need_ptr_once(map, asn1.content, asn1.size)) {
 
1294
            cli_dbgmsg("asn1_parse_mscat: failed to read countersignature encryptedDigest\n");
 
1295
            break;
 
1296
        }
 
1297
        if(!crtmgr_verify_pkcs7(cmgr, issuer, serial, asn1.content, asn1.size, hashtype, sha1, VRFY_TIME)) {
 
1298
            cli_dbgmsg("asn1_parse_mscat: pkcs7 countersignature verification failed\n");
 
1299
            break;
 
1300
        }
 
1301
 
 
1302
        cli_dbgmsg("asn1_parse_mscat: catalog succesfully parsed\n");
 
1303
    if (isBlacklisted) {
 
1304
        return 1;
 
1305
    }
 
1306
        return 0;
 
1307
    } while(0);
 
1308
 
 
1309
    cli_dbgmsg("asn1_parse_mscat: failed to parse catalog\n");
 
1310
    return 1;
 
1311
}
 
1312
 
 
1313
int asn1_load_mscat(fmap_t *map, struct cl_engine *engine) {
 
1314
    struct cli_asn1 c;
 
1315
    unsigned int size;
 
1316
    struct cli_matcher *db;
 
1317
    int i;
 
1318
 
 
1319
    if(asn1_parse_mscat(map, 0, map->len, &engine->cmgr, 0, &c.next, &size, engine))
 
1320
        return 1;
 
1321
 
 
1322
    if(asn1_expect_objtype(map, c.next, &size, &c, 0x30))
 
1323
        return 1;
 
1324
    if(asn1_expect_obj(map, &c.content, &c.size, 0x06, lenof(OID_szOID_CATALOG_LIST), OID_szOID_CATALOG_LIST))
 
1325
        return 1;
 
1326
    if(c.size) {
 
1327
        cli_dbgmsg("asn1_load_mscat: found extra data in szOID_CATALOG_LIST content\n");
 
1328
        return 1;
 
1329
    }
 
1330
    if(asn1_expect_objtype(map, c.next, &size, &c, 0x4)) /* List ID */
 
1331
        return 1;
 
1332
    if(asn1_expect_objtype(map, c.next, &size, &c, 0x17)) /* Effective date - WTF?! */
 
1333
        return 1;
 
1334
    if(asn1_expect_algo(map, &c.next, &size, lenof(OID_szOID_CATALOG_LIST_MEMBER), OID_szOID_CATALOG_LIST_MEMBER)) /* szOID_CATALOG_LIST_MEMBER */
 
1335
        return 1;
 
1336
    if(asn1_expect_objtype(map, c.next, &size, &c, 0x30)) /* hashes here */
 
1337
        return 1;
 
1338
    /* [0] is next but we don't care as it's really descriptives stuff */
 
1339
 
 
1340
    size = c.size;
 
1341
    c.next = c.content;
 
1342
    while(size) {
 
1343
        struct cli_asn1 tag;
 
1344
        if(asn1_expect_objtype(map, c.next, &size, &c, 0x30))
 
1345
            return 1;
 
1346
        if(asn1_expect_objtype(map, c.content, &c.size, &tag, 0x04)) /* TAG NAME */
 
1347
            return 1;
 
1348
        if(asn1_expect_objtype(map, tag.next, &c.size, &tag, 0x31)) /* set */
 
1349
            return 1;
 
1350
        if(c.size) {
 
1351
            cli_dbgmsg("asn1_load_mscat: found extra data in tag\n");
 
1352
            return 1;
 
1353
        }
 
1354
        while(tag.size) {
 
1355
            struct cli_asn1 tagval1, tagval2, tagval3;
 
1356
            int hashtype;
 
1357
 
 
1358
            if(asn1_expect_objtype(map, tag.content, &tag.size, &tagval1, 0x30))
 
1359
                return 1;
 
1360
            tag.content = tagval1.next;
 
1361
 
 
1362
            if(asn1_expect_objtype(map, tagval1.content, &tagval1.size, &tagval2, 0x06))
 
1363
                return 1;
 
1364
            if(tagval2.size != lenof(OID_SPC_INDIRECT_DATA_OBJID))
 
1365
                continue;
 
1366
 
 
1367
            if(!fmap_need_ptr_once(map, tagval2.content, lenof(OID_SPC_INDIRECT_DATA_OBJID))) {
 
1368
                cli_dbgmsg("asn1_load_mscat: cannot read SPC_INDIRECT_DATA\n");
 
1369
                return 1;
 
1370
            }
 
1371
            if(memcmp(tagval2.content, OID_SPC_INDIRECT_DATA_OBJID, lenof(OID_SPC_INDIRECT_DATA_OBJID)))
 
1372
                continue; /* stuff like CAT_NAMEVALUE_OBJID(1.3.6.1.4.1.311.12.2.1) and CAT_MEMBERINFO_OBJID(.2).. */
 
1373
 
 
1374
            if(asn1_expect_objtype(map, tagval2.next, &tagval1.size, &tagval2, 0x31))
 
1375
                return 1;
 
1376
            if(tagval1.size) {
 
1377
                cli_dbgmsg("asn1_load_mscat: found extra data in tag value\n");
 
1378
                return 1;
 
1379
            }
 
1380
 
 
1381
            if(asn1_expect_objtype(map, tagval2.content, &tagval2.size, &tagval1, 0x30))
 
1382
                return 1;
 
1383
            if(tagval2.size) {
 
1384
                cli_dbgmsg("asn1_load_mscat: found extra data in SPC_INDIRECT_DATA_OBJID tag\n");
 
1385
                return 1;
 
1386
            }
 
1387
 
 
1388
            if(asn1_expect_objtype(map, tagval1.content, &tagval1.size, &tagval2, 0x30))
 
1389
                return 1;
 
1390
 
 
1391
            if(asn1_expect_objtype(map, tagval2.content, &tagval2.size, &tagval3, 0x06)) /* shall have an obj 1.3.6.1.4.1.311.2.1.15 or 1.3.6.1.4.1.311.2.1.25 inside */
 
1392
                return 1;
 
1393
            if(tagval3.size != lenof(OID_SPC_PE_IMAGE_DATA_OBJID)) { /* lenof(OID_SPC_PE_IMAGE_DATA_OBJID) = lenof(OID_SPC_CAB_DATA_OBJID) = 10*/
 
1394
                cli_dbgmsg("asn1_load_mscat: bad hash type size\n");
 
1395
                return 1;
 
1396
            }
 
1397
            if(!fmap_need_ptr_once(map, tagval3.content, lenof(OID_SPC_PE_IMAGE_DATA_OBJID))) {
 
1398
                cli_dbgmsg("asn1_load_mscat: cannot read hash type\n");
 
1399
                return 1;
 
1400
            }
 
1401
            if(!memcmp(tagval3.content, OID_SPC_PE_IMAGE_DATA_OBJID, lenof(OID_SPC_PE_IMAGE_DATA_OBJID)))
 
1402
                hashtype = 2;
 
1403
            else if(!memcmp(tagval3.content, OID_SPC_CAB_DATA_OBJID, lenof(OID_SPC_CAB_DATA_OBJID)))
 
1404
                hashtype = 1;
 
1405
            else {
 
1406
                cli_dbgmsg("asn1_load_mscat: unexpected hash type\n");
 
1407
                return 1;
 
1408
            }
 
1409
 
 
1410
            if(asn1_expect_objtype(map, tagval2.next, &tagval1.size, &tagval2, 0x30))
 
1411
                return 1;
 
1412
            if(tagval1.size) {
 
1413
                cli_dbgmsg("asn1_load_mscat: found extra data after hash\n");
 
1414
                return 1;
 
1415
            }
 
1416
 
 
1417
            if(asn1_expect_algo(map, &tagval2.content, &tagval2.size, lenof(OID_sha1), OID_sha1)) /* objid 1.3.14.3.2.26 - sha1 */
 
1418
                return 1;
 
1419
 
 
1420
            if(asn1_expect_objtype(map, tagval2.content, &tagval2.size, &tagval3, 0x04))
 
1421
                return 1;
 
1422
            if(tagval2.size) {
 
1423
                cli_dbgmsg("asn1_load_mscat: found extra data in hash\n");
 
1424
                return 1;
 
1425
            }
 
1426
            if(tagval3.size != SHA1_HASH_SIZE) {
 
1427
                cli_dbgmsg("asn1_load_mscat: bad hash size %u\n", tagval3.size);
 
1428
                return 1;
 
1429
            }
 
1430
            if(!fmap_need_ptr_once(map, tagval3.content, SHA1_HASH_SIZE)) {
 
1431
                cli_dbgmsg("asn1_load_mscat: cannot read hash\n");
 
1432
                return 1;
 
1433
            }
 
1434
 
 
1435
            if(cli_debug_flag) {
 
1436
                char sha1[SHA1_HASH_SIZE*2+1];
 
1437
                for(i=0;i<SHA1_HASH_SIZE;i++)
 
1438
                    sprintf(&sha1[i*2], "%02x", ((uint8_t *)(tagval3.content))[i]);
 
1439
                cli_dbgmsg("asn1_load_mscat: got hash %s (%s)\n", sha1, (hashtype == 2) ? "PE" : "CAB");
 
1440
            }
 
1441
            if(!engine->hm_fp) {
 
1442
                if(!(engine->hm_fp = mpool_calloc(engine->mempool, 1, sizeof(*db)))) {
 
1443
                    tag.size = 1;;
 
1444
                    return 1;
 
1445
                }
 
1446
#ifdef USE_MPOOL
 
1447
                engine->hm_fp->mempool = engine->mempool;
 
1448
#endif
 
1449
            }
 
1450
            if(hm_addhash_bin(engine->hm_fp, tagval3.content, CLI_HASH_SHA1, hashtype, NULL)) {
 
1451
                cli_warnmsg("asn1_load_mscat: failed to add hash\n");
 
1452
                return 1;
 
1453
            }
 
1454
        }
 
1455
    }
 
1456
 
 
1457
    return 0;
 
1458
}
 
1459
 
 
1460
int asn1_check_mscat(struct cl_engine *engine, fmap_t *map, size_t offset, unsigned int size, uint8_t *computed_sha1) {
 
1461
    unsigned int content_size;
 
1462
    struct cli_asn1 c;
 
1463
    const void *content;
 
1464
    crtmgr certs;
 
1465
    int ret;
 
1466
 
 
1467
    if (engine->dconf->pe & PE_CONF_DISABLECERT)
 
1468
        return CL_VIRUS;
 
1469
 
 
1470
    cli_dbgmsg("in asn1_check_mscat (offset: %lu)\n", offset);
 
1471
    crtmgr_init(&certs);
 
1472
    if(crtmgr_add_roots(engine, &certs)) {
 
1473
        crtmgr_free(&certs);
 
1474
        return CL_VIRUS;
 
1475
    }
 
1476
    ret = asn1_parse_mscat(map, offset, size, &certs, 1, &content, &content_size, engine);
 
1477
    crtmgr_free(&certs);
 
1478
    if(ret)
 
1479
        return CL_VIRUS;
 
1480
 
 
1481
    if(asn1_expect_objtype(map, content, &content_size, &c, 0x30))
 
1482
        return CL_VIRUS;
 
1483
    if(asn1_expect_obj(map, &c.content, &c.size, 0x06, lenof(OID_SPC_PE_IMAGE_DATA_OBJID), OID_SPC_PE_IMAGE_DATA_OBJID))
 
1484
        return CL_VIRUS;
 
1485
    if(asn1_expect_objtype(map, c.next, &content_size, &c, 0x30))
 
1486
        return CL_VIRUS;
 
1487
    if(content_size) {
 
1488
        cli_dbgmsg("asn1_check_mscat: extra data in content\n");
 
1489
        return CL_VIRUS;
 
1490
    }
 
1491
    if(asn1_expect_algo(map, &c.content, &c.size, lenof(OID_sha1), OID_sha1))
 
1492
        return CL_VIRUS;
 
1493
 
 
1494
    if(asn1_expect_obj(map, &c.content, &c.size, 0x04, SHA1_HASH_SIZE, computed_sha1))
 
1495
        return CL_VIRUS;
 
1496
 
 
1497
    cli_dbgmsg("asn1_check_mscat: file with valid authenicode signature, whitelisted\n");
 
1498
    return CL_CLEAN;
 
1499
}