cscvs to tla changeset 3
[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  *      get_keyid - Given a public key returns the keyid.
18  *      @publickey: The key to calculate the fingerprint for.
19  */
20 uint64_t get_keyid(struct openpgp_publickey *publickey)
21 {
22         SHA1_CONTEXT sha_ctx;
23         uint64_t keyid = 0;
24         int offset = 0;
25         int i = 0;
26         unsigned char c;
27         unsigned char *buff = NULL;
28
29         assert(publickey != NULL);
30
31         switch (publickey->publickey->data[0]) {
32         case 2:
33         case 3:
34                 /*
35                  * For a type 2 or 3 key the keyid is the last 64 bits of the
36                  * public modulus n, which is stored as an MPI from offset 8
37                  * onwards.
38                  *
39                  * We need to ensure it's an RSA key.
40                  */
41                 if (publickey->publickey->data[7] == 1) {
42                         offset = (publickey->publickey->data[8] << 8) +
43                                 publickey->publickey->data[9];
44                         offset = ((offset + 7) / 8) + 2;
45
46                         for (keyid = 0, i = 0; i < 8; i++) {
47                                 keyid <<= 8;
48                                 keyid += publickey->publickey->data[offset++];
49                         }
50                 } else {
51                         fputs("Type 2 or 3 key, but not RSA.\n", stderr);
52                 }
53                 break;
54         case 4:
55                 /*
56                  * For a type 4 key the keyid is the last 64 bits of the
57                  * fingerprint, which is the 160 bit SHA-1 hash of the packet
58                  * tag, 2 octet packet length and the public key packet
59                  * including version field.
60                  */
61                 sha1_init(&sha_ctx);
62                 /*
63                  * TODO: Can this be 0x99? Are all public key packets old
64                  * format with 2 bytes of length data?
65                  */
66                 c = 0x99;
67                 sha1_write(&sha_ctx, &c, sizeof(c));
68                 c = publickey->publickey->length >> 8;
69                 sha1_write(&sha_ctx, &c, sizeof(c));
70                 c = publickey->publickey->length & 0xFF;
71                 sha1_write(&sha_ctx, &c, sizeof(c));
72                 sha1_write(&sha_ctx, publickey->publickey->data,
73                         publickey->publickey->length);
74                 sha1_final(&sha_ctx);
75                 buff = sha1_read(&sha_ctx);
76
77                 assert(buff != NULL);
78                 
79                 for (keyid = 0, i = 12; i < 20; i++) {
80                         keyid <<= 8;
81                         keyid += buff[i];
82                 }
83
84                 break;
85         default:
86                 fprintf(stderr, "Unknown key type: %d\n",
87                                 publickey->publickey->data[0]);
88         }
89
90         return keyid;
91 }