root/openpgpsdk/trunk/src/signature.c

Revision 56 (checked in by rachel, 8 years ago)

#include <string.h> added to prevent warnings about

implicit declaration of memcpy/memset

Line 
1 #include "signature.h"
2 #include "crypto.h"
3 #include "memory.h"
4 #include "build.h"
5 #include <assert.h>
6 #include <string.h>
7
8 static unsigned char prefix_md5[]={ 0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86,
9                                     0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00,
10                                     0x04,0x10 };
11
12 static unsigned char prefix_sha1[]={ 0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0E,
13                                      0x03,0x02,0x1A,0x05,0x00,0x04,0x14 };
14
15 static ops_boolean_t rsa_verify(ops_hash_algorithm_t type,
16                                 const unsigned char *hash,size_t hash_length,
17                                 const ops_rsa_signature_t *sig,
18                                 const ops_rsa_public_key_t *rsa)
19     {
20     unsigned char sigbuf[8192];
21     unsigned char hashbuf[8192];
22     int n;
23     int keysize;
24     unsigned char *prefix;
25     int plen;
26
27     keysize=(BN_num_bits(rsa->n)+7)/8;
28     // RSA key can't be bigger than 65535 bits, so...
29     assert(keysize <= sizeof hashbuf);
30     assert(BN_num_bits(sig->sig) <= 8*sizeof sigbuf);
31     BN_bn2bin(sig->sig,sigbuf);
32
33     n=ops_rsa_public_decrypt(hashbuf,sigbuf,(BN_num_bits(sig->sig)+7)/8,rsa);
34
35     if(n != keysize) // obviously, this includes error returns
36         return ops_false;
37
38     printf(" decrypt=%d ",n);
39     hexdump(hashbuf,n);
40
41     if(hashbuf[0] != 0 || hashbuf[1] != 1)
42         return ops_false;
43
44     switch(type)
45         {
46     case OPS_HASH_MD5: prefix=prefix_md5; plen=sizeof prefix_md5; break;
47     case OPS_HASH_SHA1: prefix=prefix_sha1; plen=sizeof prefix_sha1; break;
48     default: assert(0); break;
49         }
50
51     if(keysize-plen-hash_length < 10)
52         return ops_false;
53
54     for(n=2 ; n < keysize-plen-hash_length-1 ; ++n)
55         if(hashbuf[n] != 0xff)
56             return ops_false;
57
58     if(hashbuf[n++] != 0)
59         return ops_false;
60
61     if(memcmp(&hashbuf[n],prefix,plen)
62        || memcmp(&hashbuf[n+plen],hash,hash_length))
63         return ops_false;
64
65     return ops_true;
66     }
67
68 static void hash_add_key(ops_hash_t *hash,const ops_public_key_t *key)
69     {
70     ops_memory_t mem;
71
72     memset(&mem,'\0',sizeof mem);
73     ops_build_public_key(&mem,key,ops_false);
74
75     hash_add_int(hash,0x99,1);
76     hash_add_int(hash,mem.length,2);
77     hash->add(hash,mem.buf,mem.length);
78
79     ops_memory_release(&mem);
80     }
81
82 static void init_signature(ops_hash_t *hash,const ops_signature_t *sig,
83                            const ops_public_key_t *key)
84     {
85     switch(sig->hash_algorithm)
86         {
87     case OPS_HASH_MD5:
88         ops_hash_md5(hash);
89         break;
90
91     case OPS_HASH_SHA1:
92         ops_hash_sha1(hash);
93         break;
94
95     default:
96         assert(0);
97         }
98
99     hash->init(hash);
100     hash_add_key(hash,key);
101     }
102
103 static void hash_add_trailer(ops_hash_t *hash,const ops_signature_t *sig,
104                              const ops_public_key_t *signer,
105                              const unsigned char *raw_packet)
106     {
107     if(sig->version == OPS_SIG_V4)
108         {
109         hash->add(hash,raw_packet+sig->v4_hashed_data_start,
110                   sig->v4_hashed_data_length);
111         hash_add_int(hash,sig->version,1);
112         hash_add_int(hash,0xff,1);
113         hash_add_int(hash,sig->v4_hashed_data_length,4);
114         }
115     else
116         {
117         hash_add_int(hash,sig->type,1);
118         hash_add_int(hash,sig->creation_time,4);
119         }
120     }
121
122 static ops_boolean_t check_signature(ops_hash_t *hash,
123                                      const ops_signature_t *sig,
124                                      const ops_public_key_t *signer)
125     {
126     int n;
127     ops_boolean_t ret;
128     unsigned char hashout[OPS_MAX_HASH];
129
130     n=hash->finish(hash,hashout);
131     printf(" hash=");
132     //    hashout[0]=0;
133     hexdump(hashout,n);
134
135     switch(sig->key_algorithm)
136         {
137     case OPS_PKA_DSA:
138         ret=ops_dsa_verify(hashout,n,&sig->signature.dsa,&signer->key.dsa);
139         break;
140
141     case OPS_PKA_RSA:
142         ret=rsa_verify(sig->hash_algorithm,hashout,n,&sig->signature.rsa,
143                        &signer->key.rsa);
144         break;
145
146     default:
147         assert(0);
148         }
149
150     return ret;
151     }
152
153 static ops_boolean_t finalise_signature(ops_hash_t *hash,
154                                         const ops_signature_t *sig,
155                                         const ops_public_key_t *signer,
156                                         const unsigned char *raw_packet)
157     {
158     hash_add_trailer(hash,sig,signer,raw_packet);
159     return check_signature(hash,sig,signer);
160     }
161
162 ops_boolean_t
163 ops_check_certification_signature(const ops_public_key_t *key,
164                                   const ops_user_id_t *id,
165                                   const ops_signature_t *sig,
166                                   const ops_public_key_t *signer,
167                                   const unsigned char *raw_packet)
168     {
169     ops_hash_t hash;
170
171     init_signature(&hash,sig,key);
172
173     if(sig->version == OPS_SIG_V4)
174         {
175         hash_add_int(&hash,0xb4,1);
176         hash_add_int(&hash,strlen(id->user_id),4);
177         hash.add(&hash,id->user_id,strlen(id->user_id));
178         }
179     else
180         hash.add(&hash,id->user_id,strlen(id->user_id));
181
182     return finalise_signature(&hash,sig,signer,raw_packet);
183     }
184
185 ops_boolean_t
186 ops_check_subkey_signature(const ops_public_key_t *key,
187                            const ops_public_key_t *subkey,
188                            const ops_signature_t *sig,
189                            const ops_public_key_t *signer,
190                            const unsigned char *raw_packet)
191     {
192     ops_hash_t hash;
193
194     init_signature(&hash,sig,key);
195     hash_add_key(&hash,subkey);
196
197     return finalise_signature(&hash,sig,signer,raw_packet);
198     }
199
200
Note: See TracBrowser for help on using the browser.