3 #include <rpm/rpmstring.h>
4 #include <rpm/rpmpgp.h>
5 #include <rpm/rpmfileutil.h>
6 #include <rpm/rpmlog.h>
7 #include <rpm/rpmkeyring.h>
8 #include <rpm/rpmbase64.h>
10 #include "rpmio/digest.h"
23 struct rpmPubkey_s **keys;
28 static rpmPubkey rpmPubkeyUnlink(rpmPubkey key);
29 static rpmKeyring rpmKeyringUnlink(rpmKeyring keyring);
31 static int keyidcmp(const void *k1, const void *k2)
33 const struct rpmPubkey_s *key1 = *(const struct rpmPubkey_s **) k1;
34 const struct rpmPubkey_s *key2 = *(const struct rpmPubkey_s **) k2;
36 return memcmp(key1->keyid, key2->keyid, sizeof(key1->keyid));
39 rpmKeyring rpmKeyringNew(void)
41 rpmKeyring keyring = xcalloc(1, sizeof(*keyring));
45 return rpmKeyringLink(keyring);
48 rpmKeyring rpmKeyringFree(rpmKeyring keyring)
50 if (keyring == NULL) {
54 if (keyring->nrefs > 1) {
55 return rpmKeyringUnlink(keyring);
59 for (int i = 0; i < keyring->numkeys; i++) {
60 keyring->keys[i] = rpmPubkeyFree(keyring->keys[i]);
68 static rpmPubkey rpmKeyringFindKeyid(rpmKeyring keyring, rpmPubkey key)
70 rpmPubkey *found = NULL;
71 found = bsearch(&key, keyring->keys, keyring->numkeys, sizeof(*keyring->keys), keyidcmp);
72 return found ? *found : NULL;
75 int rpmKeyringAddKey(rpmKeyring keyring, rpmPubkey key)
77 if (keyring == NULL || key == NULL)
80 /* check if we already have this key */
81 if (rpmKeyringFindKeyid(keyring, key)) {
85 keyring->keys = xrealloc(keyring->keys, (keyring->numkeys + 1) * sizeof(rpmPubkey));
86 keyring->keys[keyring->numkeys] = rpmPubkeyLink(key);
88 qsort(keyring->keys, keyring->numkeys, sizeof(*keyring->keys), keyidcmp);
93 rpmKeyring rpmKeyringLink(rpmKeyring keyring)
101 static rpmKeyring rpmKeyringUnlink(rpmKeyring keyring)
109 rpmPubkey rpmPubkeyRead(const char *filename)
113 rpmPubkey key = NULL;
115 if (pgpReadPkts(filename, &pkt, &pktlen) <= 0) {
118 key = rpmPubkeyNew(pkt, pktlen);
125 rpmPubkey rpmPubkeyNew(const uint8_t *pkt, size_t pktlen)
127 rpmPubkey key = NULL;
128 pgpDigParams pgpkey = NULL;
131 if (pkt == NULL || pktlen == 0)
134 if (pgpPubkeyFingerprint(pkt, pktlen, keyid))
137 if (pgpPrtParams(pkt, pktlen, PGPTAG_PUBLIC_KEY, &pgpkey))
140 key = xcalloc(1, sizeof(*key));
141 key->pkt = xmalloc(pktlen);
142 key->pktlen = pktlen;
143 key->pgpkey = pgpkey;
145 memcpy(key->pkt, pkt, pktlen);
146 memcpy(key->keyid, keyid, sizeof(keyid));
149 return rpmPubkeyLink(key);
152 rpmPubkey rpmPubkeyFree(rpmPubkey key)
158 return rpmPubkeyUnlink(key);
160 pgpDigParamsFree(key->pgpkey);
166 rpmPubkey rpmPubkeyLink(rpmPubkey key)
174 static rpmPubkey rpmPubkeyUnlink(rpmPubkey key)
182 pgpDig rpmPubkeyDig(rpmPubkey key)
185 static unsigned char zeros[] =
186 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
192 rc = pgpPrtPkts(key->pkt, key->pktlen, dig, 0);
194 pgpDigParams pubp = pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY);
195 if (!pubp || !memcmp(pubp->signid, zeros, sizeof(pubp->signid)) ||
196 !memcmp(pubp->time, zeros, sizeof(pubp->time)) ||
197 pubp->userid == NULL) {
203 dig = pgpFreeDig(dig);
208 char * rpmPubkeyBase64(rpmPubkey key)
213 enc = rpmBase64Encode(key->pkt, key->pktlen, -1);
218 static rpmPubkey findbySig(rpmKeyring keyring, pgpDigParams sig)
220 rpmPubkey key = NULL;
222 if (keyring && sig) {
223 struct rpmPubkey_s needle;
224 memset(&needle, 0, sizeof(needle));
225 memcpy(needle.keyid, sig->signid, sizeof(needle.keyid));
227 key = rpmKeyringFindKeyid(keyring, &needle);
229 pgpDigParams pub = key->pgpkey;
230 /* Do the parameters match the signature? */
231 if ((sig->pubkey_algo != pub->pubkey_algo) ||
232 memcmp(sig->signid, pub->signid, sizeof(sig->signid))) {
240 rpmRC rpmKeyringLookup(rpmKeyring keyring, pgpDig sig)
242 rpmRC res = RPMRC_NOKEY;
243 pgpDigParams sigp = pgpDigGetParams(sig, PGPTAG_SIGNATURE);
244 rpmPubkey key = findbySig(keyring, sigp);
248 * Callers expect sig to have the key data parsed into pgpDig
249 * on (successful) return, sigh. No need to check for return
250 * here as this is validated at rpmPubkeyNew() already.
252 pgpPrtPkts(key->pkt, key->pktlen, sig, 0);
259 rpmRC rpmKeyringVerifySig(rpmKeyring keyring, pgpDigParams sig, DIGEST_CTX ctx)
261 rpmRC rc = RPMRC_FAIL;
264 pgpDigParams pgpkey = NULL;
265 rpmPubkey key = findbySig(keyring, sig);
268 pgpkey = key->pgpkey;
270 /* We call verify even if key not found for a signature sanity check */
271 rc = pgpVerifySignature(pgpkey, sig, ctx);