cscvs to tla changeset 77
[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.7 2003/06/04 20:57:09 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                  * We need to ensure it's an RSA key.
130                  */
131                 if (packet->data[7] == 1) {
132                         offset = (packet->data[8] << 8) +
133                                 packet->data[9];
134                         offset = ((offset + 7) / 8) + 2;
135
136                         for (keyid = 0, i = 0; i < 8; i++) {
137                                 keyid <<= 8;
138                                 keyid += packet->data[offset++];
139                         }
140                 } else {
141                         logthing(LOGTHING_ERROR,
142                                         "Type 2 or 3 key, but not RSA.");
143                 }
144                 break;
145         case 4:
146                 get_fingerprint(packet, buff, &length);
147                 
148                 for (keyid = 0, i = 12; i < 20; i++) {
149                         keyid <<= 8;
150                         keyid += buff[i];
151                 }
152
153                 break;
154         default:
155                 logthing(LOGTHING_ERROR, "Unknown key type: %d",
156                                 packet->data[0]);
157         }
158
159         return keyid;
160 }