]> git.sommitrealweird.co.uk Git - onak.git/blob - keyid.c
Add links to HTML index output. (Debian bug #275227)
[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 "sha1.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_CTX sha_ctx;
42         struct md5_ctx md5_context;
43         unsigned char c;
44         size_t         modlen, explen;
45
46         log_assert(fingerprint != NULL);
47         log_assert(len != NULL);
48
49         *len = 0;
50
51         switch (packet->data[0]) {
52         case 2:
53         case 3:
54                 md5_init_ctx(&md5_context);
55
56                 /*
57                  * MD5 the modulus and exponent.
58                  */
59                 modlen = ((packet->data[8] << 8) +
60                          packet->data[9] + 7) >> 3;
61                 md5_process_bytes(&packet->data[10], modlen, &md5_context);
62
63                 explen = ((packet->data[10+modlen] << 8) +
64                          packet->data[11+modlen] + 7) >> 3;
65                 md5_process_bytes(&packet->data[12 + modlen], explen,
66                                 &md5_context);
67
68                 md5_finish_ctx(&md5_context, fingerprint);
69                 *len = 16;
70
71                 break;
72
73         case 4:
74                 SHA1Init(&sha_ctx);
75                 /*
76                  * TODO: Can this be 0x99? Are all public key packets old
77                  * format with 2 bytes of length data?
78                  */
79                 c = 0x99;
80                 SHA1Update(&sha_ctx, &c, sizeof(c));
81                 c = packet->length >> 8;
82                 SHA1Update(&sha_ctx, &c, sizeof(c));
83                 c = packet->length & 0xFF;
84                 SHA1Update(&sha_ctx, &c, sizeof(c));
85                 SHA1Update(&sha_ctx, packet->data,
86                         packet->length);
87                 SHA1Final(fingerprint, &sha_ctx);
88                 *len = 20;
89
90                 break;
91         default:
92                 logthing(LOGTHING_ERROR, "Unknown key type: %d",
93                                 packet->data[0]);
94         }
95
96         return fingerprint;
97 }
98
99
100 /**
101  *      get_packetid - Given a PGP packet returns the keyid.
102  *      @packet: The packet to calculate the id for.
103  */
104 uint64_t get_packetid(struct openpgp_packet *packet)
105 {
106         uint64_t        keyid = 0;
107         int             offset = 0;
108         int             i = 0;
109         size_t          length = 0;
110         unsigned char   buff[20];
111
112         log_assert(packet != NULL);
113
114         switch (packet->data[0]) {
115         case 2:
116         case 3:
117                 /*
118                  * For a type 2 or 3 key the keyid is the last 64 bits of the
119                  * public modulus n, which is stored as an MPI from offset 8
120                  * onwards.
121                  */
122                 offset = (packet->data[8] << 8) +
123                         packet->data[9];
124                 offset = ((offset + 7) / 8) + 2;
125
126                 for (keyid = 0, i = 0; i < 8; i++) {
127                         keyid <<= 8;
128                         keyid += packet->data[offset++];
129                 }
130                 /*
131                  * Check for an RSA key; if not then log but accept anyway.
132                  * 1 == RSA
133                  * 2 == RSA Encrypt-Only
134                  * 3 == RSA Sign-Only
135                  */
136                 if (packet->data[7] < 1 || packet->data[7] > 3) {
137                         logthing(LOGTHING_NOTICE,
138                                 "Type 2 or 3 key, but not RSA: %llx (type %d)",
139                                 keyid,
140                                 packet->data[7]);
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 }