fingerprints and self signatures added
[gnupg.git] / g10 / keyid.c
1 /* keyid.c - jeyid and fingerprint handling
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 is free software; you can redistribute it and/or modify
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.
10  *
11  * G10 is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <time.h>
27 #include <assert.h>
28 #include "util.h"
29 #include "main.h"
30 #include "packet.h"
31 #include "options.h"
32 #include "mpi.h"
33 #include "keydb.h"
34
35
36
37
38 /****************
39  * Get the keyid from the secret key certificate and put it into keyid
40  * if this is not NULL. Return the 32 low bits of the keyid.
41  */
42 u32
43 keyid_from_skc( PKT_secret_cert *skc, u32 *keyid )
44 {
45     u32 lowbits;
46     u32 dummy_keyid[2];
47
48     if( !keyid )
49         keyid = dummy_keyid;
50
51     if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
52         lowbits = mpi_get_keyid( skc->d.elg.y, keyid );
53     }
54     else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
55         lowbits = mpi_get_keyid( skc->d.rsa.rsa_n, keyid );
56     }
57     else {
58         keyid[0] = keyid[1] = lowbits = 0;
59     }
60     return lowbits;
61 }
62
63
64 /****************
65  * Get the keyid from the public key certificate and put it into keyid
66  * if this is not NULL. Return the 32 low bits of the keyid.
67  */
68 u32
69 keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid )
70 {
71     u32 lowbits;
72     u32 dummy_keyid[2];
73
74     if( !keyid )
75         keyid = dummy_keyid;
76
77     if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
78         lowbits = mpi_get_keyid( pkc->d.elg.y, keyid );
79     }
80     else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
81         lowbits = mpi_get_keyid( pkc->d.rsa.rsa_n, keyid );
82     }
83     else {
84         keyid[0] = keyid[1] = lowbits = 0;
85     }
86
87     return lowbits;
88 }
89
90
91 u32
92 keyid_from_sig( PKT_signature *sig, u32 *keyid )
93 {
94     if( keyid ) {
95         keyid[0] = sig->keyid[0];
96         keyid[1] = sig->keyid[1];
97     }
98     return sig->keyid[1];
99 }
100
101 /****************
102  * return the number of bits used in the pkc
103  */
104 unsigned
105 nbits_from_pkc( PKT_public_cert *pkc )
106 {
107     if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
108         return mpi_get_nbits( pkc->d.elg.p );
109     }
110     else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
111         return mpi_get_nbits( pkc->d.rsa.rsa_n );
112     }
113     else
114         return 0;
115 }
116
117 /****************
118  * return the number of bits used in the skc
119  */
120 unsigned
121 nbits_from_skc( PKT_secret_cert *skc )
122 {
123     if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
124         return mpi_get_nbits( skc->d.elg.p );
125     }
126     else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
127         return mpi_get_nbits( skc->d.rsa.rsa_n );
128     }
129     else
130         return 0;
131 }
132
133 /****************
134  * return a string with the creation date of the pkc
135  * Note: this is alloced in a static buffer.
136  *    Format is: yyyy-mm-dd
137  */
138 const char *
139 datestr_from_pkc( PKT_public_cert *pkc )
140 {
141     static char buffer[11+5];
142     struct tm *tp;
143     time_t atime = pkc->timestamp;
144
145     tp = gmtime( &atime );
146     sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon, tp->tm_mday );
147     return buffer;
148 }
149
150 const char *
151 datestr_from_skc( PKT_secret_cert *skc )
152 {
153     static char buffer[11+5];
154     struct tm *tp;
155     time_t atime = skc->timestamp;
156
157     tp = gmtime( &atime );
158     sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon, tp->tm_mday );
159     return buffer;
160 }
161
162 const char *
163 datestr_from_sig( PKT_signature *sig )
164 {
165     static char buffer[11+5];
166     struct tm *tp;
167     time_t atime = sig->timestamp;
168
169     tp = gmtime( &atime );
170     sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon, tp->tm_mday );
171     return buffer;
172 }
173
174
175 /**************** .
176  * Return a byte array with the fingerprint for the given PKC/SKC
177  * The length of the array is returned in ret_len. Caller must free
178  * the array.
179  */
180 byte *
181 fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len )
182 {
183     PKT_public_cert pkc;
184     byte *p;
185
186     pkc.pubkey_algo = skc->pubkey_algo;
187     if( pkc.pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
188         pkc.timestamp = skc->timestamp;
189         pkc.valid_days = skc->valid_days;
190         pkc.pubkey_algo = skc->pubkey_algo;
191         pkc.d.elg.p = skc->d.elg.p;
192         pkc.d.elg.g = skc->d.elg.g;
193         pkc.d.elg.y = skc->d.elg.y;
194     }
195     else if( pkc.pubkey_algo == PUBKEY_ALGO_RSA ) {
196         pkc.d.rsa.rsa_n = skc->d.rsa.rsa_n;
197         pkc.d.rsa.rsa_e = skc->d.rsa.rsa_e;
198     }
199     p = fingerprint_from_pkc( &pkc, ret_len );
200     memset(&pkc, 0, sizeof pkc); /* not really needed */
201     return p;
202 }
203
204 byte *
205 fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len )
206 {
207     byte *p, *buf, *array;
208     size_t len;
209     unsigned n;
210
211     if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
212         RMDHANDLE md;
213         const char *dp;
214
215         md = rmd160_open(0);
216
217         {   u32 a = pkc->timestamp;
218             rmd160_putchar( md, a >> 24 );
219             rmd160_putchar( md, a >> 16 );
220             rmd160_putchar( md, a >>  8 );
221             rmd160_putchar( md, a       );
222         }
223         {   u16 a = pkc->valid_days;
224             rmd160_putchar( md, a >> 8 );
225             rmd160_putchar( md, a      );
226         }
227         rmd160_putchar( md, pkc->pubkey_algo );
228         p = buf = mpi_get_buffer( pkc->d.elg.p, &n, NULL );
229         for( ; !*p && n; p++, n-- )
230             ;
231         rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
232         m_free(buf);
233         p = buf = mpi_get_buffer( pkc->d.elg.g, &n, NULL );
234         for( ; !*p && n; p++, n-- )
235             ;
236         rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
237         m_free(buf);
238         p = buf = mpi_get_buffer( pkc->d.elg.y, &n, NULL );
239         for( ; !*p && n; p++, n-- )
240             ;
241         rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
242         m_free(buf);
243
244         dp = rmd160_final(md);
245         array = m_alloc( 20 );
246         len = 20;
247         memcpy(array, dp, 20 );
248         rmd160_close(md);
249     }
250     else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
251         MD5HANDLE md;
252
253         md = md5_open(0);
254         p = buf = mpi_get_buffer( pkc->d.rsa.rsa_n, &n, NULL );
255         for( ; !*p && n; p++, n-- )
256             ;
257         md5_write( md, p, n );
258         m_free(buf);
259         p = buf = mpi_get_buffer( pkc->d.rsa.rsa_e, &n, NULL );
260         for( ; !*p && n; p++, n-- )
261             ;
262         md5_write( md, p, n );
263         m_free(buf);
264         md5_final(md);
265         array = m_alloc( 16 );
266         len = 16;
267         memcpy(array, md5_read(md), 16 );
268         md5_close(md);
269     }
270     else {
271         array = m_alloc(1);
272         len = 0; /* ooops */
273     }
274
275     *ret_len = len;
276     return array;
277 }
278
279
280