~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/dsig.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2007-2010 Sourcefire, Inc.
 
2
 *  Copyright (C) 2003 - 2006 Tomasz Kojm <tkojm@clamav.net>
3
3
 *
4
 
 *  Authors: Tomasz Kojm
 
4
 *  Number encoding rutines are based on yyyRSA by Erik Thiele
5
5
 *
6
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.
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
9
10
 *
10
11
 *  This program is distributed in the hope that it will be useful,
11
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22
23
#include "clamav-config.h"
23
24
#endif
24
25
 
 
26
#ifdef HAVE_GMP
 
27
 
25
28
#include <stdio.h>
26
29
#include <string.h>
27
30
#include <stdlib.h>
28
31
#include <ctype.h>
 
32
#include <gmp.h>
29
33
 
30
34
#include "clamav.h"
31
35
#include "others.h"
32
36
#include "dsig.h"
33
37
#include "str.h"
34
 
#include "bignum.h"
35
38
#include "sha256.h"
36
39
 
37
40
#define CLI_NSTR "118640995551645342603070001658453189751527774412027743746599405743243142607464144767361060640655844749760788890022283424922762488917565551002467771109669598189410434699034532232228621591089508178591428456220796841621637175567590476666928698770143328137383952820383197532047771780196576957695822641224262693037"
38
41
 
39
42
#define CLI_ESTR "100001027"
40
43
 
41
 
static char cli_ndecode(unsigned char value)
 
44
#define CLI_NSTRPSS "14783905874077467090262228516557917570254599638376203532031989214105552847269687489771975792123442185817287694951949800908791527542017115600501303394778618535864845235700041590056318230102449612217458549016089313306591388590790796515819654102320725712300822356348724011232654837503241736177907784198700834440681124727060540035754699658105895050096576226753008596881698828185652424901921668758326578462003247906470982092298106789657211905488986281078346361469524484829559560886227198091995498440676639639830463593211386055065360288422394053998134458623712540683294034953818412458362198117811990006021989844180721010947"
 
45
 
 
46
#define CLI_ESTRPSS "100002053"
 
47
 
 
48
#define PSS_NBITS 2048
 
49
#define PSS_DIGEST_LENGTH 32
 
50
 
 
51
 
 
52
static char cli_ndecode(char value)
42
53
{
43
 
        unsigned int i;
 
54
        int i;
44
55
        char ncodec[] = {
45
56
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 
46
57
            'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
61
72
    return -1;
62
73
}
63
74
 
64
 
static unsigned char *cli_decodesig(const char *sig, unsigned int plen, mp_int e, mp_int n)
 
75
static unsigned char *cli_decodesig(const char *sig, int plainlen, mpz_t e, mpz_t n)
65
76
{
66
 
        int i, slen = strlen(sig), dec;
67
 
        unsigned char *plain;
68
 
        mp_int r, p, c;
69
 
 
70
 
 
71
 
    mp_init(&r);
72
 
    mp_init(&c);
73
 
    for(i = 0; i < slen; i++) {
 
77
        int i, siglen = strlen(sig), dec;
 
78
        unsigned char *decoded;
 
79
        mpz_t r, p, c;
 
80
 
 
81
 
 
82
    mpz_init(r);
 
83
    mpz_init(c);
 
84
 
 
85
    for(i = 0; i < siglen; i++) {
74
86
        if((dec = cli_ndecode(sig[i])) < 0) {
75
 
            mp_clear(&r);
76
 
            mp_clear(&c);
 
87
            mpz_clear(r);
 
88
            mpz_clear(c);
77
89
            return NULL;
78
90
        }
79
 
        mp_set_int(&r, dec);
80
 
        mp_mul_2d(&r, 6 * i, &r);
81
 
        mp_add(&r, &c, &c);
 
91
 
 
92
        mpz_set_ui(r, dec);
 
93
        mpz_mul_2exp(r, r, 6 * i);
 
94
        mpz_add(c, c, r);
82
95
    }
83
96
 
84
 
    plain = (unsigned char *) cli_calloc(plen + 1, sizeof(unsigned char));
85
 
    if(!plain) {
86
 
        cli_errmsg("cli_decodesig: Can't allocate memory for 'plain'\n");
87
 
        mp_clear(&r);
88
 
        mp_clear(&c);
 
97
    decoded = (unsigned char *) cli_calloc(plainlen + 1, sizeof(unsigned char));
 
98
    if(!decoded) {
 
99
        cli_errmsg("cli_decodesig: Can't allocate memory\n");
 
100
        mpz_clear(r);
 
101
        mpz_clear(c);
89
102
        return NULL;
90
103
    }
91
 
    mp_init(&p);
92
 
    mp_exptmod(&c, &e, &n, &p); /* plain = cipher^e mod n */
93
 
    mp_clear(&c);
94
 
    mp_set_int(&c, 256);
95
 
    for(i = plen - 1; i >= 0; i--) { /* reverse */
96
 
        mp_div(&p, &c, &p, &r);
97
 
        plain[i] = mp_get_int(&r);
98
 
    }
99
 
    mp_clear(&c);
100
 
    mp_clear(&p);
101
 
    mp_clear(&r);
102
 
 
103
 
    return plain;
 
104
 
 
105
    mpz_init(p);
 
106
    mpz_powm(p, c, e, n); /* plain = cipher^e mod n */
 
107
    mpz_clear(c);
 
108
 
 
109
    for(i = plainlen - 1; i >= 0; i--) { /* reverse */
 
110
        mpz_tdiv_qr_ui(p, r, p, 256);
 
111
        decoded[i] = mpz_get_ui(r);
 
112
    }
 
113
 
 
114
    mpz_clear(p);
 
115
    mpz_clear(r);
 
116
 
 
117
    return decoded;
 
118
}
 
119
static void cli_mgf(unsigned char *in, unsigned int inlen, unsigned char *out, unsigned int outlen)
 
120
{
 
121
        SHA256_CTX ctx;
 
122
        unsigned int i, laps;
 
123
        unsigned char cnt[4], digest[PSS_DIGEST_LENGTH];
 
124
 
 
125
 
 
126
    laps = (outlen + PSS_DIGEST_LENGTH - 1) / PSS_DIGEST_LENGTH;
 
127
 
 
128
    for(i = 0; i < laps; i++) {
 
129
        cnt[0] = (unsigned char) 0;
 
130
        cnt[1] = (unsigned char) 0;
 
131
        cnt[2] = (unsigned char) (i / 256);
 
132
        cnt[3] = (unsigned char) i;
 
133
 
 
134
        sha256_init(&ctx);
 
135
        sha256_update(&ctx, in, inlen);
 
136
        sha256_update(&ctx, cnt, sizeof(cnt));
 
137
        sha256_final(&ctx);
 
138
        sha256_digest(&ctx, digest);
 
139
 
 
140
        if(i != laps - 1)
 
141
            memcpy(&out[i * PSS_DIGEST_LENGTH], digest, PSS_DIGEST_LENGTH);
 
142
        else
 
143
            memcpy(&out[i * PSS_DIGEST_LENGTH], digest, outlen - i * PSS_DIGEST_LENGTH);
 
144
    }
 
145
}
 
146
 
 
147
int cli_versigpss(const unsigned char *sha256, const char *dsig)
 
148
{
 
149
        mpz_t n, e;
 
150
        SHA256_CTX ctx;
 
151
        unsigned char *pt, digest1[PSS_DIGEST_LENGTH], digest2[PSS_DIGEST_LENGTH], *salt;
 
152
        unsigned int plen = PSS_NBITS / 8, hlen, slen, i;
 
153
        unsigned char dblock[PSS_NBITS / 8 - PSS_DIGEST_LENGTH - 1];
 
154
        unsigned char mblock[PSS_NBITS / 8 - PSS_DIGEST_LENGTH - 1];
 
155
        unsigned char fblock[8 + 2 * PSS_DIGEST_LENGTH];
 
156
 
 
157
 
 
158
    hlen = slen = PSS_DIGEST_LENGTH;
 
159
    mpz_init_set_str(n, CLI_NSTRPSS, 10);
 
160
    mpz_init_set_str(e, CLI_ESTRPSS, 10);
 
161
 
 
162
    if(!(pt = cli_decodesig(dsig, plen, e, n))) {
 
163
        mpz_clear(n);
 
164
        mpz_clear(e);
 
165
        return CL_EDSIG;
 
166
    }
 
167
 
 
168
    mpz_clear(n);
 
169
    mpz_clear(e);
 
170
 
 
171
    if(pt[plen - 1] != 0xbc) {
 
172
        cli_dbgmsg("cli_versigpss: Incorrect signature syntax (0xbc)\n");
 
173
        free(pt);
 
174
        return CL_EDSIG;
 
175
    }
 
176
 
 
177
    memcpy(mblock, pt, plen - hlen - 1);
 
178
    memcpy(digest2, &pt[plen - hlen - 1], hlen);
 
179
    free(pt);
 
180
 
 
181
    cli_mgf(digest2, hlen, dblock, plen - hlen - 1);
 
182
 
 
183
    for(i = 0; i < plen - hlen - 1; i++)
 
184
        dblock[i] ^= mblock[i];
 
185
 
 
186
    dblock[0] &= (0xff >> 1);
 
187
 
 
188
    salt = memchr(dblock, 0x01, sizeof(dblock));
 
189
    if(!salt) {
 
190
        cli_dbgmsg("cli_versigpss: Can't find salt\n");
 
191
        return CL_EDSIG;
 
192
    }
 
193
    salt++;
 
194
 
 
195
    if((unsigned int) (dblock + sizeof(dblock) - salt) != slen) {
 
196
        cli_dbgmsg("cli_versigpss: Bad salt size\n");
 
197
        return CL_EDSIG;
 
198
    }
 
199
 
 
200
    memset(fblock, 0, 8);
 
201
    memcpy(&fblock[8], sha256, hlen);
 
202
    memcpy(&fblock[8 + hlen], salt, slen);
 
203
 
 
204
    sha256_init(&ctx);
 
205
    sha256_update(&ctx, fblock, sizeof(fblock));
 
206
    sha256_final(&ctx);
 
207
    sha256_digest(&ctx, digest1);
 
208
 
 
209
    if(memcmp(digest1, digest2, hlen)) {
 
210
        cli_dbgmsg("cli_versigpss: Signature doesn't match.\n");
 
211
        return CL_EDSIG;
 
212
    }
 
213
 
 
214
    cli_dbgmsg("cli_versigpss: Digital signature is correct.\n");
 
215
    return CL_SUCCESS;
104
216
}
105
217
 
106
218
int cli_versig(const char *md5, const char *dsig)
107
219
{
108
 
        mp_int n, e;
 
220
        mpz_t n, e;
109
221
        char *pt, *pt2;
110
222
 
111
223
 
112
224
    if(strlen(md5) != 32 || !isalnum(md5[0])) {
113
225
        /* someone is trying to fool us with empty/malformed MD5 ? */
114
226
        cli_errmsg("SECURITY WARNING: MD5 basic test failure.\n");
115
 
        return CL_EVERIFY;
 
227
        return CL_EMD5;
116
228
    }
117
229
 
118
 
    mp_init(&n);
119
 
    mp_read_radix(&n, CLI_NSTR, 10);
120
 
    mp_init(&e);
121
 
    mp_read_radix(&e, CLI_ESTR, 10);
 
230
    mpz_init_set_str(n, CLI_NSTR, 10);
 
231
    mpz_init_set_str(e, CLI_ESTR, 10);
122
232
 
123
233
    if(!(pt = (char *) cli_decodesig(dsig, 16, e, n))) {
124
 
        mp_clear(&n);
125
 
        mp_clear(&e);
126
 
        return CL_EVERIFY;
 
234
        mpz_clear(n);
 
235
        mpz_clear(e);
 
236
        return CL_EDSIG;
127
237
    }
128
238
 
129
239
    pt2 = cli_str2hex(pt, 16);
134
244
    if(strncmp(md5, pt2, 32)) {
135
245
        cli_dbgmsg("cli_versig: Signature doesn't match.\n");
136
246
        free(pt2);
137
 
        mp_clear(&n);
138
 
        mp_clear(&e);
139
 
        return CL_EVERIFY;
 
247
        mpz_clear(n);
 
248
        mpz_clear(e);
 
249
        return CL_EDSIG;
140
250
    }
141
251
 
142
252
    free(pt2);
143
 
    mp_clear(&n);
144
 
    mp_clear(&e);
 
253
    mpz_clear(n);
 
254
    mpz_clear(e);
145
255
 
146
256
    cli_dbgmsg("cli_versig: Digital signature is correct.\n");
147
257
    return CL_SUCCESS;
148
258
}
149
 
 
150
 
#define HASH_LEN    32
151
 
#define SALT_LEN    32
152
 
#define PAD_LEN     (2048 / 8)
153
 
#define BLK_LEN     (PAD_LEN - HASH_LEN - 1)
154
 
int cli_versig2(const unsigned char *sha256, const char *dsig_str, const char *n_str, const char *e_str)
155
 
{
156
 
        unsigned char *decoded, digest1[HASH_LEN], digest2[HASH_LEN], digest3[HASH_LEN], *salt;
157
 
        unsigned char mask[BLK_LEN], data[BLK_LEN], final[8 + 2 * HASH_LEN], c[4];
158
 
        unsigned int i, rounds;
159
 
        SHA256_CTX ctx;
160
 
        mp_int n, e;
161
 
 
162
 
    mp_init(&e);
163
 
    mp_read_radix(&e, e_str, 10);
164
 
    mp_init(&n);
165
 
    mp_read_radix(&n, n_str, 10);
166
 
 
167
 
    decoded = cli_decodesig(dsig_str, PAD_LEN, e, n);
168
 
    mp_clear(&n);
169
 
    mp_clear(&e);
170
 
    if(!decoded)
171
 
        return CL_EVERIFY;
172
 
 
173
 
    if(decoded[PAD_LEN - 1] != 0xbc) {
174
 
        free(decoded);
175
 
        return CL_EVERIFY;
176
 
    }
177
 
 
178
 
    memcpy(mask, decoded, BLK_LEN);
179
 
    memcpy(digest2, &decoded[BLK_LEN], HASH_LEN);
180
 
    free(decoded);
181
 
 
182
 
    c[0] = c[1] = 0;
183
 
    rounds = (BLK_LEN + HASH_LEN - 1) / HASH_LEN;
184
 
    for(i = 0; i < rounds; i++) {
185
 
        c[2] = (unsigned char) (i / 256);
186
 
        c[3] = (unsigned char) i;
187
 
        sha256_init(&ctx);
188
 
        sha256_update(&ctx, digest2, HASH_LEN);
189
 
        sha256_update(&ctx, c, 4);
190
 
        sha256_final(&ctx, digest3);
191
 
        if(i + 1 == rounds)
192
 
            memcpy(&data[i * 32], digest3, BLK_LEN - i * HASH_LEN);
193
 
        else
194
 
            memcpy(&data[i * 32], digest3, HASH_LEN);
195
 
    }
196
 
 
197
 
    for(i = 0; i < BLK_LEN; i++)
198
 
        data[i] ^= mask[i];
199
 
    data[0] &= (0xff >> 1);
200
 
 
201
 
    if(!(salt = memchr(data, 0x01, BLK_LEN)))
202
 
        return CL_EVERIFY;
203
 
    salt++;
204
 
 
205
 
    if(data + BLK_LEN - salt != SALT_LEN)
206
 
        return CL_EVERIFY;
207
 
 
208
 
    memset(final, 0, 8);
209
 
    memcpy(&final[8], sha256, HASH_LEN);
210
 
    memcpy(&final[8 + HASH_LEN], salt, SALT_LEN);
211
 
 
212
 
    sha256_init(&ctx);
213
 
    sha256_update(&ctx, final, sizeof(final));
214
 
    sha256_final(&ctx, digest1);
215
 
 
216
 
    return memcmp(digest1, digest2, HASH_LEN) ? CL_EVERIFY : CL_SUCCESS;
217
 
}
 
259
#endif