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