cscvs to tla changeset 139
[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.10 2004/05/31 22:04:51 noodles Exp $
9  */
10
11 #include <sys/types.h>
12
13 #include "assert.h"
14 #include "keyid.h"
15 #include "keystructs.h"
16 #include "log.h"
17 #include "md5.h"
18 #include "sha1.h"
19
20
21 /**
22  *      get_keyid - Given a public key returns the keyid.
23  *      @publickey: The key to calculate the id for.
24  */
25 uint64_t get_keyid(struct openpgp_publickey *publickey)
26 {
27         return (get_packetid(publickey->publickey));
28 }
29
30 /**
31  *      get_fingerprint - Given a public key returns the fingerprint.
32  *      @publickey: The key to calculate the id for.
33  *      @fingerprint: The fingerprint (must be at least 20 bytes of space). 
34  *      @len: The length of the returned fingerprint.
35  *
36  *      This function returns the fingerprint for a given public key. As Type 3
37  *      fingerprints are 16 bytes and Type 4 are 20 the len field indicates
38  *      which we've returned.
39  */
40 unsigned char *get_fingerprint(struct openpgp_packet *packet,
41         unsigned char *fingerprint,
42         size_t *len)
43 {
44         SHA1_CTX sha_ctx;
45         struct md5_ctx md5_context;
46         unsigned char c;
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_ctx(&md5_context);
58
59                 /*
60                  * MD5 the modulus and exponent.
61                  */
62                 modlen = ((packet->data[8] << 8) +
63                          packet->data[9] + 7) >> 3;
64                 md5_process_bytes(&packet->data[10], modlen, &md5_context);
65
66                 explen = ((packet->data[10+modlen] << 8) +
67                          packet->data[11+modlen] + 7) >> 3;
68                 md5_process_bytes(&packet->data[12 + modlen], explen,
69                                 &md5_context);
70
71                 md5_finish_ctx(&md5_context, fingerprint);
72                 *len = 16;
73
74                 break;
75
76         case 4:
77                 SHA1Init(&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                 SHA1Update(&sha_ctx, &c, sizeof(c));
84                 c = packet->length >> 8;
85                 SHA1Update(&sha_ctx, &c, sizeof(c));
86                 c = packet->length & 0xFF;
87                 SHA1Update(&sha_ctx, &c, sizeof(c));
88                 SHA1Update(&sha_ctx, packet->data,
89                         packet->length);
90                 SHA1Final(fingerprint, &sha_ctx);
91                 *len = 20;
92
93                 break;
94         default:
95                 logthing(LOGTHING_ERROR, "Unknown key type: %d",
96                                 packet->data[0]);
97         }
98
99         return fingerprint;
100 }
101
102
103 /**
104  *      get_packetid - Given a PGP packet returns the keyid.
105  *      @packet: The packet to calculate the id for.
106  */
107 uint64_t get_packetid(struct openpgp_packet *packet)
108 {
109         uint64_t        keyid = 0;
110         int             offset = 0;
111         int             i = 0;
112         size_t          length = 0;
113         unsigned char   buff[20];
114
115         assert(packet != NULL);
116
117         switch (packet->data[0]) {
118         case 2:
119         case 3:
120                 /*
121                  * For a type 2 or 3 key the keyid is the last 64 bits of the
122                  * public modulus n, which is stored as an MPI from offset 8
123                  * onwards.
124                  */
125                 offset = (packet->data[8] << 8) +
126                         packet->data[9];
127                 offset = ((offset + 7) / 8) + 2;
128
129                 for (keyid = 0, i = 0; i < 8; i++) {
130                         keyid <<= 8;
131                         keyid += packet->data[offset++];
132                 }
133                 /*
134                  * Check for an RSA key; if not then log but accept anyway.
135                  * 1 == RSA
136                  * 2 == RSA Encrypt-Only
137                  * 3 == RSA Sign-Only
138                  */
139                 if (packet->data[7] < 1 || packet->data[7] > 3) {
140                         logthing(LOGTHING_NOTICE,
141                                 "Type 2 or 3 key, but not RSA: %llx (type %d)",
142                                 keyid,
143                                 packet->data[7]);
144                 }
145                 break;
146         case 4:
147                 get_fingerprint(packet, buff, &length);
148                 
149                 for (keyid = 0, i = 12; i < 20; i++) {
150                         keyid <<= 8;
151                         keyid += buff[i];
152                 }
153
154                 break;
155         default:
156                 logthing(LOGTHING_ERROR, "Unknown key type: %d",
157                                 packet->data[0]);
158         }
159
160         return keyid;
161 }