5 #include <rpm/rpmstring.h>
6 #include <rpm/rpmpgp.h>
7 #include <rpm/rpmfileutil.h>
8 #include <rpm/rpmlog.h>
9 #include <rpm/rpmkeyring.h>
10 #include <rpm/rpmbase64.h>
12 #include "rpmio/digest.h"
22 pthread_rwlock_t lock;
26 struct rpmPubkey_s **keys;
29 pthread_rwlock_t lock;
32 static int keyidcmp(const void *k1, const void *k2)
34 const struct rpmPubkey_s *key1 = *(const struct rpmPubkey_s **) k1;
35 const struct rpmPubkey_s *key2 = *(const struct rpmPubkey_s **) k2;
37 return memcmp(key1->keyid, key2->keyid, sizeof(key1->keyid));
40 rpmKeyring rpmKeyringNew(void)
42 rpmKeyring keyring = xcalloc(1, sizeof(*keyring));
46 pthread_rwlock_init(&keyring->lock, NULL);
50 rpmKeyring rpmKeyringFree(rpmKeyring keyring)
55 pthread_rwlock_wrlock(&keyring->lock);
56 if (--keyring->nrefs == 0) {
58 for (int i = 0; i < keyring->numkeys; i++) {
59 keyring->keys[i] = rpmPubkeyFree(keyring->keys[i]);
63 pthread_rwlock_unlock(&keyring->lock);
64 pthread_rwlock_destroy(&keyring->lock);
67 pthread_rwlock_unlock(&keyring->lock);
72 static rpmPubkey rpmKeyringFindKeyid(rpmKeyring keyring, rpmPubkey key)
74 rpmPubkey *found = NULL;
75 found = bsearch(&key, keyring->keys, keyring->numkeys, sizeof(*keyring->keys), keyidcmp);
76 return found ? *found : NULL;
79 int rpmKeyringAddKey(rpmKeyring keyring, rpmPubkey key)
81 int rc = 1; /* assume already seen key */
82 if (keyring == NULL || key == NULL)
85 /* check if we already have this key, but always wrlock for simplicity */
86 pthread_rwlock_wrlock(&keyring->lock);
87 if (!rpmKeyringFindKeyid(keyring, key)) {
88 keyring->keys = xrealloc(keyring->keys,
89 (keyring->numkeys + 1) * sizeof(rpmPubkey));
90 keyring->keys[keyring->numkeys] = rpmPubkeyLink(key);
92 qsort(keyring->keys, keyring->numkeys, sizeof(*keyring->keys),
96 pthread_rwlock_unlock(&keyring->lock);
101 rpmKeyring rpmKeyringLink(rpmKeyring keyring)
104 pthread_rwlock_wrlock(&keyring->lock);
106 pthread_rwlock_unlock(&keyring->lock);
111 rpmPubkey rpmPubkeyRead(const char *filename)
115 rpmPubkey key = NULL;
117 if (pgpReadPkts(filename, &pkt, &pktlen) <= 0) {
120 key = rpmPubkeyNew(pkt, pktlen);
127 rpmPubkey rpmPubkeyNew(const uint8_t *pkt, size_t pktlen)
129 rpmPubkey key = NULL;
130 pgpDigParams pgpkey = NULL;
133 if (pkt == NULL || pktlen == 0)
136 if (pgpPubkeyKeyID(pkt, pktlen, keyid))
139 if (pgpPrtParams(pkt, pktlen, PGPTAG_PUBLIC_KEY, &pgpkey))
142 key = xcalloc(1, sizeof(*key));
143 key->pkt = xmalloc(pktlen);
144 key->pktlen = pktlen;
145 key->pgpkey = pgpkey;
147 memcpy(key->pkt, pkt, pktlen);
148 memcpy(key->keyid, keyid, sizeof(keyid));
149 pthread_rwlock_init(&key->lock, NULL);
155 rpmPubkey *rpmGetSubkeys(rpmPubkey mainkey, int *count)
157 rpmPubkey *subkeys = NULL;
158 pgpDigParams *pgpsubkeys = NULL;
159 int pgpsubkeysCount = 0;
162 if (mainkey && !pgpPrtParamsSubkeys(mainkey->pkt, mainkey->pktlen,
163 mainkey->pgpkey, &pgpsubkeys, &pgpsubkeysCount)) {
165 subkeys = xmalloc(pgpsubkeysCount * sizeof(*subkeys));
167 for (i = 0; i < pgpsubkeysCount; i++) {
168 rpmPubkey subkey = xcalloc(1, sizeof(*subkey));
171 /* Packets with all subkeys already stored in main key */
175 subkey->pgpkey = pgpsubkeys[i];
176 memcpy(subkey->keyid, pgpsubkeys[i]->signid, sizeof(subkey->keyid));
178 pthread_rwlock_init(&subkey->lock, NULL);
182 *count = pgpsubkeysCount;
187 rpmPubkey rpmPubkeyFree(rpmPubkey key)
192 pthread_rwlock_wrlock(&key->lock);
193 if (--key->nrefs == 0) {
194 pgpDigParamsFree(key->pgpkey);
196 pthread_rwlock_unlock(&key->lock);
197 pthread_rwlock_destroy(&key->lock);
200 pthread_rwlock_unlock(&key->lock);
205 rpmPubkey rpmPubkeyLink(rpmPubkey key)
208 pthread_rwlock_wrlock(&key->lock);
210 pthread_rwlock_unlock(&key->lock);
215 pgpDig rpmPubkeyDig(rpmPubkey key)
218 static unsigned char zeros[] =
219 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
226 pthread_rwlock_rdlock(&key->lock);
227 rc = pgpPrtPkts(key->pkt, key->pktlen, dig, 0);
228 pthread_rwlock_unlock(&key->lock);
231 pgpDigParams pubp = pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY);
232 if (!pubp || !memcmp(pubp->signid, zeros, sizeof(pubp->signid)) ||
233 pubp->time == 0 || pubp->userid == NULL) {
239 dig = pgpFreeDig(dig);
244 char * rpmPubkeyBase64(rpmPubkey key)
249 pthread_rwlock_rdlock(&key->lock);
250 enc = rpmBase64Encode(key->pkt, key->pktlen, -1);
251 pthread_rwlock_unlock(&key->lock);
256 pgpDigParams rpmPubkeyPgpDigParams(rpmPubkey key)
258 pgpDigParams params= NULL;
261 params = key->pgpkey;
266 static rpmPubkey findbySig(rpmKeyring keyring, pgpDigParams sig)
268 rpmPubkey key = NULL;
270 if (keyring && sig) {
271 struct rpmPubkey_s needle;
272 memset(&needle, 0, sizeof(needle));
273 memcpy(needle.keyid, sig->signid, sizeof(needle.keyid));
275 key = rpmKeyringFindKeyid(keyring, &needle);
277 pgpDigParams pub = key->pgpkey;
278 /* Do the parameters match the signature? */
279 if ((sig->pubkey_algo != pub->pubkey_algo) ||
280 memcmp(sig->signid, pub->signid, sizeof(sig->signid))) {
288 rpmRC rpmKeyringLookup(rpmKeyring keyring, pgpDig sig)
290 pthread_rwlock_rdlock(&keyring->lock);
292 rpmRC res = RPMRC_NOKEY;
293 pgpDigParams sigp = pgpDigGetParams(sig, PGPTAG_SIGNATURE);
294 rpmPubkey key = findbySig(keyring, sigp);
298 * Callers expect sig to have the key data parsed into pgpDig
299 * on (successful) return, sigh. No need to check for return
300 * here as this is validated at rpmPubkeyNew() already.
302 pgpPrtPkts(key->pkt, key->pktlen, sig, 0);
306 pthread_rwlock_unlock(&keyring->lock);
310 rpmRC rpmKeyringVerifySig(rpmKeyring keyring, pgpDigParams sig, DIGEST_CTX ctx)
312 rpmRC rc = RPMRC_FAIL;
315 pthread_rwlock_rdlock(&keyring->lock);
317 pgpDigParams pgpkey = NULL;
318 rpmPubkey key = findbySig(keyring, sig);
321 pgpkey = key->pgpkey;
323 /* We call verify even if key not found for a signature sanity check */
324 rc = pgpVerifySignature(pgpkey, sig, ctx);
326 pthread_rwlock_unlock(&keyring->lock);