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

« back to all changes in this revision

Viewing changes to libclamav/dsig.c

  • Committer: Bazaar Package Importer
  • Author(s): SpecialK
  • Date: 2008-01-04 11:25:36 UTC
  • mfrom: (19.2.4 hardy)
  • Revision ID: james.westby@ubuntu.com-20080104112536-b23litkqiv48cm9o
Tags: 0.92~dfsg-2~feisty1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  Copyright (C) 2003 - 2006 Tomasz Kojm <tkojm@clamav.net>
3
 
 *  RSASSA-PSS code (C) Sensory Networks, Inc.
4
 
 *  Written by Tomasz Kojm
5
3
 *
6
4
 *  Number encoding rutines are based on yyyRSA by Erik Thiele
7
5
 *
36
34
#include "others.h"
37
35
#include "dsig.h"
38
36
#include "str.h"
39
 
#include "sha256.h"
40
37
 
41
38
#define CLI_NSTR "118640995551645342603070001658453189751527774412027743746599405743243142607464144767361060640655844749760788890022283424922762488917565551002467771109669598189410434699034532232228621591089508178591428456220796841621637175567590476666928698770143328137383952820383197532047771780196576957695822641224262693037"
42
39
 
43
40
#define CLI_ESTR "100001027"
44
41
 
45
 
#define CLI_NSTRPSS "14783905874077467090262228516557917570254599638376203532031989214105552847269687489771975792123442185817287694951949800908791527542017115600501303394778618535864845235700041590056318230102449612217458549016089313306591388590790796515819654102320725712300822356348724011232654837503241736177907784198700834440681124727060540035754699658105895050096576226753008596881698828185652424901921668758326578462003247906470982092298106789657211905488986281078346361469524484829559560886227198091995498440676639639830463593211386055065360288422394053998134458623712540683294034953818412458362198117811990006021989844180721010947"
46
 
 
47
 
#define CLI_ESTRPSS "100002053"
48
 
 
49
 
#define PSS_NBITS 2048
50
 
#define PSS_DIGEST_LENGTH 32
51
 
 
52
 
 
53
 
static char cli_ndecode(char value)
 
42
static unsigned char cli_ndecode(unsigned char value)
54
43
{
55
 
        int i;
 
44
        unsigned int i;
56
45
        char ncodec[] = {
57
46
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 
58
47
            'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
73
62
    return -1;
74
63
}
75
64
 
76
 
static unsigned char *cli_decodesig(const char *sig, int plainlen, mpz_t e, mpz_t n)
 
65
unsigned char *cli_decodesig(const char *sig, unsigned int plen, mpz_t e, mpz_t n)
77
66
{
78
 
        int i, siglen = strlen(sig), dec;
79
 
        unsigned char *decoded;
 
67
        int i, slen = strlen(sig), dec;
 
68
        unsigned char *plain;
80
69
        mpz_t r, p, c;
81
70
 
82
71
 
83
72
    mpz_init(r);
84
73
    mpz_init(c);
85
74
 
86
 
    for(i = 0; i < siglen; i++) {
 
75
    for(i = 0; i < slen; i++) {
87
76
        if((dec = cli_ndecode(sig[i])) < 0) {
88
77
            mpz_clear(r);
89
78
            mpz_clear(c);
95
84
        mpz_add(c, c, r);
96
85
    }
97
86
 
98
 
    decoded = (unsigned char *) cli_calloc(plainlen + 1, sizeof(unsigned char));
99
 
    if(!decoded) {
100
 
        cli_errmsg("cli_decodesig: Can't allocate memory\n");
 
87
    plain = (unsigned char *) cli_calloc(plen + 1, sizeof(unsigned char));
 
88
    if(!plain) {
 
89
        cli_errmsg("cli_decodesig: Can't allocate memory for 'plain'\n");
101
90
        mpz_clear(r);
102
91
        mpz_clear(c);
103
92
        return NULL;
107
96
    mpz_powm(p, c, e, n); /* plain = cipher^e mod n */
108
97
    mpz_clear(c);
109
98
 
110
 
    for(i = plainlen - 1; i >= 0; i--) { /* reverse */
 
99
    for(i = plen - 1; i >= 0; i--) { /* reverse */
111
100
        mpz_tdiv_qr_ui(p, r, p, 256);
112
 
        decoded[i] = mpz_get_ui(r);
 
101
        plain[i] = mpz_get_ui(r);
113
102
    }
114
103
 
115
104
    mpz_clear(p);
116
105
    mpz_clear(r);
117
106
 
118
 
    return decoded;
119
 
}
120
 
static void cli_mgf(unsigned char *in, unsigned int inlen, unsigned char *out, unsigned int outlen)
121
 
{
122
 
        SHA256_CTX ctx;
123
 
        unsigned int i, laps;
124
 
        unsigned char cnt[4], digest[PSS_DIGEST_LENGTH];
125
 
 
126
 
 
127
 
    laps = (outlen + PSS_DIGEST_LENGTH - 1) / PSS_DIGEST_LENGTH;
128
 
 
129
 
    for(i = 0; i < laps; i++) {
130
 
        cnt[0] = (unsigned char) 0;
131
 
        cnt[1] = (unsigned char) 0;
132
 
        cnt[2] = (unsigned char) (i / 256);
133
 
        cnt[3] = (unsigned char) i;
134
 
 
135
 
        sha256_init(&ctx);
136
 
        sha256_update(&ctx, in, inlen);
137
 
        sha256_update(&ctx, cnt, sizeof(cnt));
138
 
        sha256_final(&ctx);
139
 
        sha256_digest(&ctx, digest);
140
 
 
141
 
        if(i != laps - 1)
142
 
            memcpy(&out[i * PSS_DIGEST_LENGTH], digest, PSS_DIGEST_LENGTH);
143
 
        else
144
 
            memcpy(&out[i * PSS_DIGEST_LENGTH], digest, outlen - i * PSS_DIGEST_LENGTH);
145
 
    }
146
 
}
147
 
 
148
 
int cli_versigpss(const unsigned char *sha256, const char *dsig)
149
 
{
150
 
        mpz_t n, e;
151
 
        SHA256_CTX ctx;
152
 
        unsigned char *pt, digest1[PSS_DIGEST_LENGTH], digest2[PSS_DIGEST_LENGTH], *salt;
153
 
        unsigned int plen = PSS_NBITS / 8, hlen, slen, i;
154
 
        unsigned char dblock[PSS_NBITS / 8 - PSS_DIGEST_LENGTH - 1];
155
 
        unsigned char mblock[PSS_NBITS / 8 - PSS_DIGEST_LENGTH - 1];
156
 
        unsigned char fblock[8 + 2 * PSS_DIGEST_LENGTH];
157
 
 
158
 
 
159
 
    hlen = slen = PSS_DIGEST_LENGTH;
160
 
    mpz_init_set_str(n, CLI_NSTRPSS, 10);
161
 
    mpz_init_set_str(e, CLI_ESTRPSS, 10);
162
 
 
163
 
    if(!(pt = cli_decodesig(dsig, plen, e, n))) {
164
 
        mpz_clear(n);
165
 
        mpz_clear(e);
166
 
        return CL_EDSIG;
167
 
    }
168
 
 
169
 
    mpz_clear(n);
170
 
    mpz_clear(e);
171
 
 
172
 
    if(pt[plen - 1] != 0xbc) {
173
 
        cli_dbgmsg("cli_versigpss: Incorrect signature syntax (0xbc)\n");
174
 
        free(pt);
175
 
        return CL_EDSIG;
176
 
    }
177
 
 
178
 
    memcpy(mblock, pt, plen - hlen - 1);
179
 
    memcpy(digest2, &pt[plen - hlen - 1], hlen);
180
 
    free(pt);
181
 
 
182
 
    cli_mgf(digest2, hlen, dblock, plen - hlen - 1);
183
 
 
184
 
    for(i = 0; i < plen - hlen - 1; i++)
185
 
        dblock[i] ^= mblock[i];
186
 
 
187
 
    dblock[0] &= (0xff >> 1);
188
 
 
189
 
    salt = memchr(dblock, 0x01, sizeof(dblock));
190
 
    if(!salt) {
191
 
        cli_dbgmsg("cli_versigpss: Can't find salt\n");
192
 
        return CL_EDSIG;
193
 
    }
194
 
    salt++;
195
 
 
196
 
    if((unsigned int) (dblock + sizeof(dblock) - salt) != slen) {
197
 
        cli_dbgmsg("cli_versigpss: Bad salt size\n");
198
 
        return CL_EDSIG;
199
 
    }
200
 
 
201
 
    memset(fblock, 0, 8);
202
 
    memcpy(&fblock[8], sha256, hlen);
203
 
    memcpy(&fblock[8 + hlen], salt, slen);
204
 
 
205
 
    sha256_init(&ctx);
206
 
    sha256_update(&ctx, fblock, sizeof(fblock));
207
 
    sha256_final(&ctx);
208
 
    sha256_digest(&ctx, digest1);
209
 
 
210
 
    if(memcmp(digest1, digest2, hlen)) {
211
 
        cli_dbgmsg("cli_versigpss: Signature doesn't match.\n");
212
 
        return CL_EDSIG;
213
 
    }
214
 
 
215
 
    cli_dbgmsg("cli_versigpss: Digital signature is correct.\n");
216
 
    return CL_SUCCESS;
 
107
    return plain;
217
108
}
218
109
 
219
110
int cli_versig(const char *md5, const char *dsig)