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