]> git.sommitrealweird.co.uk Git - onak.git/blob - keyid.c
cscvs to tla changeset 123
[onak.git] / keyid.c
1 /*
2  * keyid.c - Routines to calculate key IDs.
3  *
4  * Jonathan McDowell <noodles@earth.li>
5  *
6  * Copyright 2002 Project Purple
7  *
8  * $Id: keyid.c,v 1.8 2003/11/01 19:25:15 noodles Exp $
9  */
10
11 #include <sys/types.h>
12
13 #include "keyid.h"
14 #include "keystructs.h"
15 #include "log.h"
16 #include "md5.h"
17 #include "sha.h"
18
19
20 /**
21  *      get_keyid - Given a public key returns the keyid.
22  *      @publickey: The key to calculate the id for.
23  */
24 uint64_t get_keyid(struct openpgp_publickey *publickey)
25 {
26         return (get_packetid(publickey->publickey));
27 }
28
29 /**
30  *      get_fingerprint - Given a public key returns the fingerprint.
31  *      @publickey: The key to calculate the id for.
32  *      @fingerprint: The fingerprint (must be at least 20 bytes of space). 
33  *      @len: The length of the returned fingerprint.
34  *
35  *      This function returns the fingerprint for a given public key. As Type 3
36  *      fingerprints are 16 bytes and Type 4 are 20 the len field indicates
37  *      which we've returned.
38  */
39 unsigned char *get_fingerprint(struct openpgp_packet *packet,
40         unsigned char *fingerprint,
41         size_t *len)
42 {
43         SHA1_CONTEXT sha_ctx;
44         MD5_CONTEXT md5_ctx;
45         unsigned char c;
46         unsigned char *buff = NULL;
47         size_t         modlen, explen;
48
49         assert(fingerprint != NULL);
50         assert(len != NULL);
51
52         *len = 0;
53
54         switch (packet->data[0]) {
55         case 2:
56         case 3:
57                 md5_init(&md5_ctx);
58
59                 /*
60                  * MD5 the modulus and exponent.
61                  */
62                 modlen = ((packet->data[8] << 8) +
63                          packet->data[9] + 7) >> 3;
64                 md5_write(&md5_ctx, &packet->data[10], modlen);
65
66                 explen = ((packet->data[10+modlen] << 8) +
67                          packet->data[11+modlen] + 7) >> 3;
68                 md5_write(&md5_ctx, &packet->data[12 + modlen], explen);
69
70                 md5_final(&md5_ctx);
71                 buff = md5_read(&md5_ctx);
72
73                 *len = 16;
74                 memcpy(fingerprint, buff, *len);
75
76                 break;
77
78         case 4:
79                 sha1_init(&sha_ctx);
80                 /*
81                  * TODO: Can this be 0x99? Are all public key packets old
82                  * format with 2 bytes of length data?
83                  */
84                 c = 0x99;
85                 sha1_write(&sha_ctx, &c, sizeof(c));
86                 c = packet->length >> 8;
87                 sha1_write(&sha_ctx, &c, sizeof(c));
88                 c = packet->length & 0xFF;
89                 sha1_write(&sha_ctx, &c, sizeof(c));
90                 sha1_write(&sha_ctx, packet->data,
91                         packet->length);
92                 sha1_final(&sha_ctx);
93                 buff = sha1_read(&sha_ctx);
94
95                 *len = 20;
96                 memcpy(fingerprint, buff, *len);
97                 break;
98         default:
99                 logthing(LOGTHING_ERROR, "Unknown key type: %d",
100                                 packet->data[0]);
101         }
102
103         return fingerprint;
104 }
105
106
107 /**
108  *      get_packetid - Given a PGP packet returns the keyid.
109  *      @packet: The packet to calculate the id for.
110  */
111 uint64_t get_packetid(struct openpgp_packet *packet)
112 {
113         uint64_t        keyid = 0;
114         int             offset = 0;
115         int             i = 0;
116         size_t          length = 0;
117         unsigned char   buff[20];
118
119         assert(packet != NULL);
120
121         switch (packet->data[0]) {
122         case 2:
123         case 3:
124                 /*
125                  * For a type 2 or 3 key the keyid is the last 64 bits of the
126                  * public modulus n, which is stored as an MPI from offset 8
127                  * onwards.
128                  */
129                 offset = (packet->data[8] << 8) +
130                         packet->data[9];
131                 offset = ((offset + 7) / 8) + 2;
132
133                 for (keyid = 0, i = 0; i < 8; i++) {
134                         keyid <<= 8;
135                         keyid += packet->data[offset++];
136                 }
137                 /*
138                  * I thought we needed to ensure it's an RSA key, but pks
139                  * doesn't seem to care and I've seen some type 3 keys.
140                  * So just log a warning.
141                  */
142                 if (packet->data[7] != 1) {
143                         logthing(LOGTHING_NOTICE,
144                                 "Type 2 or 3 key, but not RSA: %llx (type %d)",
145                                 keyid,
146                                 packet->data[7]);
147                 }
148                 break;
149         case 4:
150                 get_fingerprint(packet, buff, &length);
151                 
152                 for (keyid = 0, i = 12; i < 20; i++) {
153                         keyid <<= 8;
154                         keyid += buff[i];
155                 }
156
157                 break;
158         default:
159                 logthing(LOGTHING_ERROR, "Unknown key type: %d",
160                                 packet->data[0]);
161         }
162
163         return keyid;
164 }